前端面试中常见的手写代码集合

来源 | 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 的优先级高于 bindreturn 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 bfunction _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 请求* 并利用浏览器对
