- 功能上 与 原生 保持一致
- 参数判断,边界处理等不保证(这样代码少,方便理解)。
- 符合ecma的标准
尽量满足2个标准,除非无法实现
bind
Function.prototype.myBind = function (context, ...partArgs) {
let fn = this
let prototype = fn.prototype
function boundFn(...args) {
// new
if (this instanceof boundFn) {
return new fn(...partArgs, ...args)
}
// 函数调用
return fn.call(context, ...partArgs, ...args)
}
// 用于instanceof
// ecma规定值应该为undefined,但实现不了
boundFn.prototype = prototype
return boundFn
}
call
- 在obj上调用函数,函数的
this
就会指向obj
Function.prototype.myCall = function (context, ...args) {
// null||undefined context指向window
// Objet:基本类型封装成对象, 对象类型直接返回
context = Object(context ?? window);
let fn = this;
let id = Symbol();
// 减少对context的侵入
Object.defineProperty(context, id, {configurable: true, enumerable: false, writable: false, value: fn})
try {
return context[id](...args); //执行fn
} finally {
delete context[id]; //删除方法
}
};
apply
Function.prototype.myApply = function (context, args) {
return this.myCall(context, ...args)
};
兼容es3
上面的代码只支持ES5,对于Symbol,函数...
传参进行兼容处理。
Symbol
function mySymbol(obj) {
let id = Math.round().toString(32).slice(2, 10)
return Object.hasOwnProperty(obj, id) ? mySymbol(obj) : id
}
函数传参
function callFn(fn, args) {
let call = new Function('fn', 'args', 'return fn(args.joun)')
return call(fn, args)
}