手写call、apply、bind
区别:
- call 接收多个参数
- apply 接收数组
- bind 返回函数,不直接调用。能够分两次接收参数。
原理上就是把function挂在target对象上面,通过target.function 的方式,隐式的将执行上下文修改。
myCall
Function.prototype.myCall = function(context = window, ...args) {
if (typeof this !== 'function') {
throw new TypeError('xxx');
}
const uniqueKey = Symbol();
context[uniqueKey] = this;
const res = context[uniqueKey](...args);
delete context[uniqueKey];
return res;
}
myApply
Function.prototype.myApply = function(context = window, args = []) {
if (typeof this !== 'function') {
throw new TypeError('xxx');
}
if (!Array.isArray(args)) {
throw new TypeError('xxx');
}
const uniqueKey = Symbol();
context[uniqueKey] = this;
const res = context[uniqueKey](...args);
delete context[uniqueKey];
return res;
}
myBind
Function.prototype.myBind = function(context, ...args) {
if (typeof this !== 'function') {
throw new TypeError('xxx');
}
const callback = this;
return function(...newArgs) {
const uniqueKey = Symbol();
context[uniqueKey] = callback;
const res = context[uniqueKey](...args, ...newArgs);
delete context[uniqueKey];
return res;
}
}
手写Instanceof
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
function myInstanceof(left, right) {
// 如果 left 不是对象,直接返回 false
if (typeof left !== 'object' || left === null) return false;
// 获取left对象的原型;
let proto = Object.getPrototypeOf(left)
// 构造函数的 prototype 对象是否在对象的原型链上
while (true) {
if (!proto) return false;
if (proto === right.prototype) return true;
// 如果没有找到,就继续从其原型上找,Object.getPrototypeOf方法用来获取指定对象的原型
proto = Object.getPrototypeOf(proto);
}
}
手写new
const myNew = (constructor, ...args) => {
// 1. 创建proto 指向构造函数prototype的对象
const that = Object.create(constructor.prototype);
// 2. 调用构造函数。传入参数
const obj = constructor.apply(that, args);
if(obj && typeof obj === 'object') {
return obj;
} else {
return that;
}
}