Appearance
思路
- 模拟this调用
- 解析剩余参数
- 参数如何传到函数中
- context为null时处理
- 处理函数非法的情况
- 删除额外新增的变量,最好采用symbol
js
const getFunctionArgs = (funcArgs, startIndex = 0) => {
const result = []
for(let i = startIndex, len = funcArgs.length; i < len; i++) {
result.push(funcArgs[i])
}
return result;
}
const checkFunction = (fn) => {
return typeof fn === 'function'
}
Function.prototype.myCall = function(context) {
if(!(checkFunction(this))) {
throw new Error('not function');
}
const restArgs = getFunctionArgs(arguments, 1);
context = context || globalThis;
context.__fn = this;
const result = eval(`context.__fn(${restArgs})`)
delete context.__fn
return result
}
Function.prototype.myApply = function(context, args = []) {
if(!checkFunction(this)) throw new Error('not function');
context = context || globalThis;
context.__fn = this;
const result = eval(`context.__fn(${args})`)
delete context.__fn
return result
}
Function.prototype.myBind = function (context, ...initArgs) {
if(!checkFunction(this)) throw new Error('not function');
const fn = this;
const temp = function () {}
temp.prototype = this.prototype;
const fbind = function (...args) {
return fn.myCall(this instanceof fn ? this : context, ...initArgs, ...args)
}
fbind.prototype = new temp()
return fbind
}
function newFn(constructor, ...args) {
const obj = Object.create(null);
obj.__proto__ = constructor.prototype;
constructor.myApply(obj, args)
return obj
}