First, from the following points to consider how to implement these functions:
- The first parameter is not passed, then the default context for the window;
- Changed this point, so that the new object can perform this function, and can accept parameters.
So call us first to achieve
Function.prototype.myCall = function(context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
context = context || window
context.fn = this
const args = [...arguments].slice(1)
const result = context.fn(...args)
delete context.fn
return result
}
analysis:
- First, context is optional, if you do not pass, then the default context for the window;
- Next, create a fn property to the context, and set the value as a function of the need to call;
- Because the call number of parameters can be passed as a parameter to a function call, it needs to be stripped out parameters, and then call the function on the function and object deletion (because the object itself is not the function, but in the scope of delivery called, make a temporary property).
The idea is to achieve the above call, apply implementation is similar, except that the processing parameters, it is not one of the analysis of ideas.
Function.prototype.myApply = function(context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
context = context || window
context.fn = this
let result
// 处理参数和 call 有区别
if (arguments[1]) {
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
delete context.fn
return result
}
bind implementation compared to other two functions are slightly more complicated, because the need to return a bind function, you need to determine the number of border issues, the following are bind implementation:
Function.prototype.myBind = function (context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
const _this = this
const args = [...arguments].slice(1)
// 返回一个函数
return function F() {
// 因为返回了一个函数,我们可以 new F(),所以需要判断
if (this instanceof F) {
return new _this(...args, ...arguments)
}
return _this.apply(context, args.concat(...arguments))
}
}
analysis:
- And the first steps before implementation almost, not go into details.
- bind returns a function, a function is invoked in two ways, one is called directly, one is the new way through, the way we first is called directly;
- For direct calls, here we chose to apply the ways, but parameters need to pay attention to the following: bind because such code can achieve similar f.bind (obj, 1) (2), so we need to both sides of the argument splicing up, so there is this realization args.concat (... arguments);
- Finally, it is through new ways, in this case, it will not be any change in this way, so for this we need to ignore the return function of this.