前端面试题汇总,不定期更新~ 😋
前端面试题汇总
js 相关
['1', '2', '3'].map(parseInt)
2、call实现
Function.prototype.call = function (context) {
context = context || window;
var fn = Symbol(); // added
context[fn] = this; // changed
let args = [...arguments].slice(1);
let result = context[fn](...args); // changed
delete context[fn]; // changed
return result;
}
this 指向
this的指向是在函数调用的时候确定下来的, this的指向大致可以分为五种。
1、 默认绑定: 指向全局对象,严格模式为undefined
2、 隐式绑定: 谁调用 this 就指向谁
3、 显示绑定call,apply,bind
4、 new绑定
5、 es6的箭头函数 (箭头函数的 this 始终指向函数定义时的 this,而非执行时)
this绑定优先级:
箭头函数 -> new绑定 -> 显示绑定call/bind/apply -> 隐式绑定 -> 默认绑定
数组扁平化
//已知如下数组:
//var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
//编写一个程序将数组扁平化去并除其中重复部分数据,最终得到一个升序且不重复的数组。[题目参考](https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/8)
[...new Set(arr.toString().split(",").sort((a,b)=>{ return a-b }))]
//或
Array.from(new Set(arr.flat(Infinity))).sort((a,b)=>{ return a-b})
function flatten(arr) {
return arr.reduce((result, item)=> {
return result.concat(Array.isArray(item) ? flatten(item) : item)
}, [])
}
React 中 setState 什么时候是同步的,什么时候是异步的?
解答
实现一个 sleep 函数
const sleep = (time) => {
return new Promise(resolve => setTimeout(resolve, time))
}
为什么在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty
(1) Object.defineProperty无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应;
(2) Object.defineProperty只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。Proxy可以劫持整个对象,并返回一个新的对象。
(3) Proxy不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。
解答
instanceof 的实现
function instanceof(L, R) { //L是表达式左边,R是表达式右边
var O = R.prototype;
L = L.__proto__;
while(true) {
if (L === null)
return false;
if (L === O)
return true;
L = L.__proto__;
}
}
如何将一个数组打乱
arr.sort(() => Math.random() - 0.5)
//sort方法使用了插入排序(目标长度小于10)和快排,元素之间的比较远小于n(n-1)/2,因此有些元素间没有随机交换的可能,使得该方法不够随机。
function shuffle(arr) {
let m = arr.length;
while (m > 1){
let index = Math.floor(Math.random() * m--);
[arr[m] , arr[index]] = [arr[index] , arr[m]]
}
return arr;
}
//复杂度为O(n)。从后向前遍历,不断将当前元素与随机位置的元素(除去已遍历的部分)进行交换。
trim 方法模拟
function trim(str) {
return str.replace(/^\s+|\s+$/g, '')
}
千分位分隔
function format(str) {
return str.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
}
Vue 组件 data 为什么必须是函数
当一个组件被定义, data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象。
JS数据类型判断
Javascript 7 种数据类型包含 基本类型:String、Number、Boolean、Symbol、Undefined、Null,引用类型:Object
1、typeof : typeof可以测试出number、string、boolean、undefined、function 及 Object (null及数组都为Object)
2、instanceof : instanceof 来判断否为实例,instanceof 判断两个对象是否属于实例关系, 但不能判断对象实例具体属于哪种类型。
3、constructor : 当一个函数F被定义时,JS引擎为函数添加 prototype 原型,再在 prototype 上添加一个 constructor 属性,并让其指向 F 的引用, var f = new F() 实例的 constructor 指向F f.constructor == F (例:’’.constructor === String)
4、toString :Object 的原型方法调用 toString (例 Object.prototype.toString.call(‘’))
网页从输入网址到渲染完成经历了哪些过程
CLICK ME
1、浏览器输入网址
2、域名解析:浏览器缓存 ➡️ 系统缓存 ➡️ 本地host文件 ➡️ 路由器缓存 ➡️ 智能DNS查询
3、三次握手以建立TCP连接
4、浏览器请求资源文件html、js、css,http的缓存(强缓存或、协商缓存)
5、浏览器拿到html构建DOM树,获得外部CSS文件的数据构建CSSOM树,再将DOM树与CSSOM树结合在一起生成render tree,后遍历渲染树开始布局(执行顺序JavaScript执行、style样式计算、layout布局、paint绘制、composite合成)
6、当浏览器的HTML解析器遇到一个script标记时会暂停构建DOM,加载js文件,解析器进行词法分析成词法单元、语法分析生成AST(最后转换成机器码)、预编译(先变量提升,在预定义函数)、解释执行js
7、js如果样式或DOM有更改,则浏览器会重新生成render tree,进行重绘和重排
如何停掉 Promise 链
链接
Promise.all 使用及实现
链接
链接
实现 Promise.finally
Promise.prototype.finally = function (fn) {
return this.then(value => {
fn()
return value
}, reason => {
fn()
throw reason
});
}
resolve/reject
static resolve(val) {
return new Promise((resolve, reject) => {
resolve(val)
})
}
static reject(val) {
return new Promise((resolve, reject) => {
reject(val)
})
}
Promise实现 timeout
链接
理解 ES6 Iterator
链接
Javascript中装饰器的实现原理
Javascript中装饰器的实现原理
Javascript 中的装饰器
setState 同步异步
深入setState
BFC 概念
理解 BFC 原理
webpack Scope Hoisting
Scope Hoisting