] Unlock 3 in advance 160cb6a8884f5d
The original intention of writing this series of articles is to "let every front-end engineer master high-frequency knowledge points to help work." This is the fifteenth cut of the front-end hundred questions cut. I hope that friends will pay attention to the public account "Kite Holder" and arm their minds with knowledge.
has briefly summarized the three methods of call, apply, and bind in the hundred questions cut [014]. The functions of these three are the same. All of them can change the this point, so that an object can call methods that it does not have. This section Will deeply understand the realization principle of these three.
15.1 call()
15.1.1 Basics
call()
method uses a specifiedthis
value and one or more parameters to call a function. The return value is the return value of calling the function with the this value and parameters provided by the caller. If the method has no return value, it returns undefined.Basic usage:
function.call(thisArg, arg1, arg2, ...)
Small scale chopper
function method(val1, val2) {
return this.a + this.b + val1 + val2;
}
const obj = {
a: 1,
b: 2
};
console.log(method.call(obj, 3, 4)); // 10
15.1.2 Implementation
To implement a call function, you will go through the following steps:
- Get the first parameter (note that when the first parameter is null or undefined, this points to window), and build the object
- Pass the corresponding function into the object
- Get parameters and execute the corresponding function
- Delete the function in the object to eliminate side effects
- Return result
Function.prototype.myCall = function (context, ...args) {
// 获取第一个参数(注意第一个参数为null或undefined时,this指向window),构建对象
context = context ? Object(context) : window;
// 将对应函数传入该对象中
context.fn = this;
// 获取参数并执行相应函数
let result = context.fn(...args);
// 消除副作用
delete context.fn;
// 返回结果
return result;
}
// ……
console.log(method.myCall(obj, 3, 4)); // 10
15.2 apply()
15.2.1 Basics
apply()
method calls a function with a giventhis
, and the parameters provided in the form of an array (or array-like object). The return value is the result of the function specifying this value and parameters. The difference betweencall()
andapply()
call()
method accepts a parameter list , while theapply()
method accepts a parameter array ;Basic usage
func.apply(thisArg, [argsArray])
Small scale chopper
function method(val1, val2) {
return this.a + this.b + val1 + val2;
}
const obj = {
a: 1,
b: 2
};
console.log(method.apply(obj, [3, 4])); // 10
15.2.2 Implementation
The difference between apply and call is mainly the difference in parameters, so the implementation steps of call are roughly similar, as shown below:
Function.prototype.myApply = function (context, arr) {
context = context ? Object(context) : window;
context.fn = this;
let result = arr ? context.fn(...arr) : context.fun();
delete context.fn;
return result;
}
// ……
console.log(method.myApply(obj, [3, 4])); // 10
15.3 bind()
15.3.1 Basics
bind()
method creates a new function, inbind()
is called, this new functionthis
is designated asbind()
the first parameter, and the remaining arguments as parameters of the new function for use during calls. The return value of the function is a copy of the original function, and has the specified this value and initial parameters.Basic usage
function.bind(thisArg[, arg1[, arg2[, ...]]])
Small scale chopper
function method(val1, val2) {
return this.a + this.b + val1 + val2;
}
const obj = {
a: 1,
b: 2
};
const bindMethod = method.bind(obj, 3, 4);
console.log(bindMethod()); // 10
15.3.2 Implementation
The realization of a bind function is relatively more complicated, and the following points should be noted:
- Can change this point;
- What is returned is a function;
- Able to accept multiple parameters;
- Support currying form of parameter passing fun(arg1)(arg2);
- After obtaining the return value of calling bind(), if you use the new call (as a constructor), the context passed in by bind() becomes invalid.
Function.prototype.myBind = function (context, ...args) {
if (typeof(this) !== 'function') {
throw new TypeError('The bound object needs to be a function');
}
const self = this;
// 定义一个中装函数
const fNOP = function() {};
const fBound = function(...fBoundArgs) {
// 利用apply改变this指向
// 接受多个参数+支持柯里化形式传参
// 当返回值通过new调用时,this指向当前实例 (因为this是当前实例,实例的隐士原型上有fNOP的实例(fnop);fnop instanceof fNOP为true)
return self.apply(this instanceof fNOP ? this : context, [...args, ...fBoundArgs]);
}
// 将调用函数的原型赋值到中转函数的原型上
if (this.prototype) {
fNOP.prototype = this.prototype;
}
// 通过原型的方式继承调用函数的原型
fBound.prototype = new fNOP();
return fBound;
}
1. If you think this article is good, share it, like it, and let more people see it
2. Follow the official account holders, and kill the front-end 100 questions with the account owner
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。