前端面试中常见的手写代码集合
来源 | https://juejin.im/post/5c9edb066fb9a05e267026dc
作者 | 我不吃饼干呀
CSS 部分
1、两栏布局
要求:垂直两栏,左边固定右边自适应。
Document
.outer {
height: 100px;
margin-bottom: 10px;
}
.left {
background: tomato;
height: 100px;
}
.right {
background: gold;
height: 100px;
}
/* 浮动 */
.outer1 .left {
width: 200px;
float: left;
}
.outer1 .right {
width: auto;
margin-left: 200px;
}
/* flex */
.outer2 {
display: flex;
}
.outer2 .left {
flex-grow: 0;
flex-shrink: 0;
flex-basis: 200px;
}
.outer2 .right {
flex: auto; /* 1 1 auto */
}
/* position */
.outer3 {
position: relative;
}
.outer3 .left {
position: absolute;
width: 200px;
}
.outer3 .right {
margin-left: 200px;
}
/* position again */
.outer4 {
position: relative;
}
.outer4 .left {
width: 200px;
}
.outer4 .right {
position: absolute;
top: 0;
left: 200px;
right: 0;
}
1-left
1-right
2-left
2-right
3-left
3-right
4-left
4-right
2、三栏布局
要求:垂直三栏布局,左右两栏宽度固定,中间自适应
Document
.outer, .left, .middle, .right {
height: 100px;
margin-bottom: 5px;
}
.left {
background: tomato;
}
.middle {
background: lightgreen;
}
.right {
background: gold;
}
/* 左右分别设置绝对定位 中间设置外边距 */
.outer1 {
position: relative;
}
.outer1 .left {
position: absolute;
width: 100px;
}
.outer1 .middle {
margin: 0 200px 0 100px;
}
.outer1 .right {
position: absolute;
width: 200px;
top: 0;
right: 0;
}
/* flex 布局 */
.outer2 {
display: flex;
}
.outer2 .left {
flex: 0 0 100px;
}
.outer2 .middle {
flex: auto;
}
.outer2 .right {
flex: 0 0 200px;
}
/* 浮动布局 但是 html 中 middle要放到最后 */
.outer3 .left {
float: left;
width: 100px;
}
.outer3 .right {
float: right;
width: 200px;
}
.outer3 .middle {
margin: 0 200px 0 100px;
}
1-left
1-middle
1-right
2-left
2-middle
2-right
3-left
3-right
3-middle
3、圣杯布局 和 双飞翼布局
和三栏布局要求相同,不过中间列要写在前面保证优先渲染。
Document
.outer, .left, .middle, .right {
height: 100px;
margin-bottom: 5px;
}
.left {
background: tomato;
}
.middle {
background: lightgreen;
}
.right {
background: gold;
}
/* 圣杯布局 通过浮动和负边距实现 */
.outer1 {
padding: 0 200px 0 100px;
}
.outer1 .middle {
width: 100%;
float: left;
}
.outer1 .left {
width: 100px;
float: left;
margin-left: -100%;
position: relative;
left: -100px;
}
.outer1 .right {
width: 200px;
float: left;
margin-left: -200px;
position: relative;
left: 200px;
}
/* 双飞翼布局 */
.outer2 .middle-wrapper {
width: 100%;
float: left;
}
.outer2 .middle {
margin: 0 200px 0 100px;
}
.outer2 .left {
width: 100px;
float: left;
margin-left: -100%;
}
.outer2 .right {
width: 200px;
float: left;
margin-left: -200px;
}
圣杯-middle
圣杯-left
圣杯-right
双飞翼布局-middle
双飞翼布局-left
双飞翼布局-right
3、三角形
实现一个三角形
常见题目,通过 border 实现
三角形
.box1, .box2, .box3, .box4 {
height: 0px;
width: 0px;
float: left;
border-style: solid;
margin: 10px;
}
.box1 { /* 等腰直角 */
border-width: 100px;
border-color: tomato transparent transparent transparent;
}
.box2 { /* 等边 */
border-width: 100px 173px;
border-color: transparent tomato transparent transparent;
}
.box3 { /* 等腰 */
border-width: 100px 80px;
border-color: transparent transparent tomato transparent;
}
.box4 { /* 其他 */
border-width: 100px 90px 80px 70px;
border-color: transparent transparent transparent tomato;
}
/* 都是像对于屏幕宽度的比例 */
.square1 {
width: 10%;
height: 10vw;
background: red;
}
/* margin/padding 百分比是相对父元素 width 的 */
.square2 {
width: 20%;
height: 0;
padding-top: 20%;
background: orange;
}
/* 通过子元素 margin */
.square3 {
width: 30%;
overflow: hidden; /* 触发 BFC */
background: yellow;
}
.square3::after {
content: '';
display: block;
margin-top: 100%; /* 高度相对于 square3 的 width */
}
Document
/* 通过 border 和 border-radius 实现 1/4 圆 */
.sector1 {
height: 0;
width: 0;
border: 100px solid;
border-radius: 50%;
border-color: turquoise tomato tan thistle;
}
/* 类似三角形的做法加上父元素 overflow: hidden; 也可以实现任意弧度圆 */
.sector2 {
height: 100px;
width: 200px;
border-radius: 100px 100px 0 0;
overflow: hidden;
}
.sector2::after {
content: '';
display: block;
height: 0;
width: 0;
border-style: solid;
border-width: 100px 58px 0;
border-color: tomato transparent;
transform: translate(42px,0);
}
/* 通过子元素 rotateZ 和父元素 overflow: hidden 实现任意弧度扇形(此处是60°) */
.sector3 {
height: 100px;
width: 100px;
border-top-right-radius: 100px;
overflow: hidden;
/* background: gold; */
}
.sector3::after {
content: '';
display: block;
height: 100px;
width: 100px;
background: tomato;
transform: rotateZ(-30deg);
transform-origin: left bottom;
}
/* 通过 skewY 实现一个60°的扇形 */
.sector4 {
height: 100px;
width: 100px;
border-top-right-radius: 100px;
overflow: hidden;
}
.sector4::after {
content: '';
display: block;
height: 100px;
width: 100px;
background: tomato;
transform: skewY(-30deg);
transform-origin: left bottom;
}
/* 通过渐变设置60°扇形 */
.sector5 {
height: 200px;
width: 200px;
background: tomato;
border-radius: 50%;
background-image: linear-gradient(150deg, transparent 50%, #fff 50%),
linear-gradient(90deg, #fff 50%, transparent 50%);
}
水平垂直居中
.outer {
height: 200px;
width: 200px;
background: tomato;
margin: 10px;
float: left;
position: relative;
}
.inner {
height: 100px;
width: 100px;
background: black;
}
/*
* 通过 position 和 margin 居中
* 缺点:需要知道 inner 的长宽
*/
.inner1 {
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px;
margin-left: -50px;
}
/*
* 通过 position 和 margin 居中 (2
*/
.inner2 {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
/*
* 通过 flex 进行居中
*/
.outer3 {
display: flex;
justify-content: center;
align-items: center;
}
/**
* 通过 position 和 transform 居中
*/
.inner4 {
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
position: absolute;
}
清除浮动
.outer {
width: 200px;
background: tomato;
margin: 10px;
position: relative;
}
.inner {
height: 100px;
width: 100px;
background: pink;
margin: 10px;
float: left;
}
/* 伪元素 */
.outer1::after {
content: '';
display: block;
clear: both;
}
/* 创建 BFC */
.outer2 {
overflow: hidden;
}
Document
.bg {
height: 666px;
width: 100%;
font-size: 60px;
text-align: center;
}
.dialog {
z-index: 999;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(0, 0, 0, 0.5);
}
.dialog .content {
min-height: 300px;
width: 600px;
background: #fff;
border-radius: 5px;
border: 1px solid #ebeef5;
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
页面内容
弹出框
Document
body,html {
margin: 0;
padding: 0;
}
/* flex 实现 */
/* .nav {
display: flex;
height: 30px;
border: 1px solid #000;
padding: 3px;
overflow-x: auto;
}
.nav::-webkit-scrollbar {
display: none;
}
.item {
flex: 0 0 200px;
height: 30px;
margin-right: 5px;
background: gray;
} */
/* inline-block 和 white-space: nowrap; 实现 */
.nav {
height: 30px;
padding: 3px;
border: 1px solid #000;
overflow-x: auto;
white-space: nowrap;
}
.nav::-webkit-scrollbar {
display: none;
}
.item {
display: inline-block;
width: 200px;
height: 30px;
margin-right: 5px;
background: gray;
}
item1
item2
item3
item4
item5
item6
item7
item8
item9
CSS 部分完,总结,Flex 无敌。
JavaScript 部分
1、手写 bind、call 和 apply
Function.prototype.bind = function(context, ...bindArgs) {
// func 为调用 bind 的原函数
const func = this;
context = context || window;
if (typeof func !== 'function') {
throw new TypeError('Bind must be called on a function');
}
// bind 返回一个绑定 this 的函数
return function(...callArgs) {
let args = bindArgs.concat(callArgs);
if (this instanceof func) {
// 意味着是通过 new 调用的 而 new 的优先级高于 bind
return new func(...args);
}
return func.call(context, ...args);
}
}
// 通过隐式绑定实现
Function.prototype.call = function(context, ...args) {
context = context || window;
context.func = this;
if (typeof context.func !== 'function') {
throw new TypeError('call must be called on a function');
}
let res = context.func(...args);
delete context.func;
return res;
}
Function.prototype.apply = function(context, args) {
context = context || window;
context.func = this;
if (typeof context.func !== 'function') {
throw new TypeError('apply must be called on a function');
}
let res = context.func(...args);
delete context.func;
return res;
}
2、实现一个继承
// 参考 You Dont Know JavaScript 上卷
// 基类
function Base() {
}
// 派生类
function Derived() {
Base.call(this);
}
// 将派生类的原型的原型链挂在基类的原型上
Object.setPrototypeOf(Derived.prototype, Base.prototype);
3、实现一个 new
// 手动实现一个 new 关键字的功能的函数 _new(fun, args) --> new fun(args)
function _new(fun, ...args) {
if (typeof fun !== 'function') {
return new Error('参数必须是一个函数');
}
let obj = Object.create(fun.prototype);
let res = fun.call(obj, ...args);
if (res !== null && (typeof res === 'object' || typeof res === 'function')) {
return res;
}
return obj;
}
4、实现一个 instanceof
// a instanceof b
function _instanceof(a, b) {
while (a) {
if (a.__proto__ === b.prototype) return true;
a = a.__proto__;
}
return false;
}
5、手写 jsonp 的实现
// foo 函数将会被调用 传入后台返回的数据
function foo(data) {
console.log('通过jsonp获取后台数据:', data);
document.getElementById('data').innerHTML = data;
}
/**
* 通过手动创建一个 script 标签发送一个 get 请求
* 并利用浏览器对