前言
本篇文章将会列出一些前端面试可能现场手撕的代码,如果你遇到这方面的题目,欢迎评论,我们可以让它更加健全
一、快速排序
function quickSort(arr) {
if (arr.length <= 1) return arr; // 只有一个自然是有序的
let index = Math.floor(arr.length / 2); // 获取参考值索引,我们要做的就是将比参考值大的都放到右边,否则放在左边
let value = arr.splice(index, 1); // 这里用到splice是因为,参考值是不需要遍历的所以把它切走
let left = [], right = [];
for (let i=0; i<arr.length; i++) {
arr[i] < value ? left.push(arr[i]) : right.push(arr[i]);
}
return quickSort(left).concat(value, quickSort(right)); // 这里用到递归,懂就算了,不懂就可以这样理解: 总之会一直切下去,知道只剩一个,命中quickSort的if,然后返回
}
二、深拷贝
function deepClone(target) {
if (typeof target !== 'object' || target == null) return target; // 除了数组和对象,都可以直接返回了
let result = Array.isArray(target) ? [] : {}; // 上述两种情况二选一
for (let key in target) {
if (target.hasOwnProperty(key)) {
result[key] = deepClon(target[key]); // 又是亲爱的递归
}
}
return result;
}
三、call apply bind
// 三个改变this指向的操作
Function.prototype.call = function() {
let arr = Array.form(arguments); // 接收传入的变量
let context = arr.shift() || windows; // 第一个为它新的this指向,如果没有就是window
context.fn = this; // 这个this指的是 xxx.call 的xxx
let result = context.fn(...arr); // 将xxx在新的this执行里面执行一遍
delete context.fn; // 删除自己添加的属性
return result;
}
Function.prototype.apply = function() { // apply和call除了传参形式不一样之外没有区别,就不啰嗦了
let arr = Array.form(arguments);
let context = arr[0] || windows;
let args = arr[1];
context.fn = this;
let result = context.fn(...args);
delete context.fn;
return result;
}
Funciton.prototype.bind = function() { // bind传值方式和call一样,但是bind返回的是一个改变this指向的函数,并不会自动运行一遍
let arr = Array.form(arguments);
let context = arr.shift() || windows;
let self = this; // 将xxx.bind 的xxx用self保存起来,这是因为,在下一个函数里面this就不在,是xxx了,但是self保存后在下一个函数中依然是xxx,很快就看到了
return function() {
let args = arr.concat(Array.form(arguments));
return self.call(context, ...args); // 很快就在这,我们需要改变的就是xxx的this指向,但是在这里this指的并不是xxx,所以前面用self保存了但是的this(也就是xxx)
}
}
四、new 干了什么?
function myNew (target, ..args) {
let obj = {}; // 它先创建了一个空对象
obj.__proto__ = target.prototype; // 然后让空对象的隐式原型指向了构造函数的prototype;
target.call(obj, ...args); // 然后在新创的对象中,执行了一次构造函数
return obj;
}
五、instanceof
这里需要对原型和原型链有一定的了解,我这里提供局部的一点来帮助理解一下操作,大神自动忽略
function _instanceof(L, R) {
let target = R.prototype;
L = L.__proto__;
while(true) {
if (L === target) return true;
if (L === null) return false;
L = L.__proto__;
}
}