【面试中常考的源码实现】面试中常被考到的手撕代码:
- call/apply/bind
- instanceof
- 深拷贝
- 基于 ES5/ES6 实现“双向绑定”
- promise相关
Function.prototype.call2 = function(context) {
if (typeof this !== "function") {
throw new TypeError("Error");
}// 默认上下文是window
context = context || window;
// 保存默认的fn
const { fn } = context;
// 将函数本身作为对象context的属性调用,自动绑定this
context.fn = this;
const args = [...arguments].slice(1);
const result = context.fn(...args);
// 恢复默认的fn
context.fn = fn;
return result;
};
apply
Function.prototype.apply2 = function(context) {
if (typeof this !== "function") {
throw new TypeError("Error");
}context = context || window;
const { fn } = context;
context.fn = this;
let result;
if (Array.isArray(arguments[1])) {
// 通过...运算符将数组转换为用逗号分隔的参数序列
result = context.fn(...arguments[1]);
} else {
result = context.fn();
}context.fn = fn;
return result;
};
bind
Function.prototype.bind2 = function(context) {
if (typeof this !== "function") {
throw new TypeError("Error");
}const that = this;
// 保留之前的参数,为了下面的参数拼接
const args = [...arguments].slice(1);
return function F() {
// 如果被new创建实例,不会被改变上下文!
if (this instanceof F) {
return new that(...args, ...arguments);
}// args.concat(...arguments): 拼接之前和现在的参数
// 注意:arguments是个类Array的Object, 用解构运算符..., 直接拿值拼接
return that.apply(context, args.concat(...arguments));
};
};
2.instanceof代码实现
function instanceof2(left, right) {
let prototype = right.prototype;
// 沿着left的原型链, 看看是否有何prototype相等的节点
left = left.__proto__;
while (1) {
if (left === null || left === undefined) {
return false;
}
if (left === prototype) {
return true;
}
left = left.__proto__;
}
}
3.深拷贝
function cloneArr(src, target) {
for (let item of src) {
if (Array.isArray(item)) {
target.push(cloneArr(item, []));
} else if (typeof item === "object") {
target.push(deepClone(item, {}));
} else {
target.push(item);
}
}
return target;
}
function deepClone(src, target) {
const keys = Reflect.ownKeys(src);
let value = https://www.it610.com/article/null;
for (let key of keys) {
value = src[key];
if (Array.isArray(value)) {
target[key] = cloneArr(value, []);
} else if (typeof value ==="object") {
// 如果是对象而且不是数组, 那么递归调用深拷贝
target[key] = deepClone(value, {});
} else {
target[key] = value;
}
}return target;
}
4.基于 ES5/ES6 实现“双向绑定” ES5的Object.defineProperty()
Document - 锐客网
>
const obj = {
value: ""
};
function onKeyUp(event) {
obj.value = https://www.it610.com/article/event.target.value;
}// 对 obj.value 进行拦截
Object.defineProperty(obj,"value", {
get: function() {
return value;
},
set: function(newValue) {
value = https://www.it610.com/article/newValue;
document.querySelector("#value").innerHTML = newValue;
// 更新视图层
document.querySelector("input").value = https://www.it610.com/article/newValue;
// 数据模型改变
}
});
值是:id="value">
ES6的proxy
Document - 锐客网
>
const obj = {}const newObj = new Proxy(obj, {
get: function(target, key, receiver) {
return Reflect.get(target, key, receiver)
},
set: function(target, key, value, receiver) {
if(key === 'value') {
document.querySelector('#value').innerHTML = value
document.querySelector('input').value = https://www.it610.com/article/value
}
return Reflect.set(target, key, value, receiver)
}
})function onKeyUp(event) {
newObj.value = event.target.value
}值是:id="value">
推荐阅读
- 程序员|【高级Java架构师系统学习】毕业一年萌新的Java大厂面经,最新整理
- linux笔记|linux 常用命令汇总(面向面试)
- jvm|【JVM】JVM08(java内存模型解析[JMM])
- 面试|我经历的IT公司面试及离职感受(转)
- android-面试|我经历的IT公司面试及离职感受
- Java|一个月内面了30家企业,不断对比薪资,我从18K变成了38K
- vue|Vue面试常用详细总结
- java人生|35K 入职华为Java开发那天,我哭了(这 5 个月做的一切都值了)
- Android|年后备战金三银四(Android面试吃透这一篇就没有拿不到的offer......)
- java|后悔没有早点遇到它 , 直接从 12K 涨到了 30K