手写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(obj, constructor) {
// 如果 obj 是 null 或 undefined,直接返回 false
if (obj === null || obj === undefined) {
return false;
}
// 获取对象的原型
let proto = Object.getPrototypeOf(obj);
// 遍历原型链
while (proto !== null) {
// 如果找到了构造函数的 prototype 属性,返回 true
if (proto === constructor.prototype) {
return true;
}
// 继续向上查找原型链
proto = Object.getPrototypeOf(proto);
}
// 如果遍历完原型链都没有找到,返回 false
return false;
}
手写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;
}
}