What are the similarities and differences between the three?
Instructions
Function.call(object, arg1, arg2...)
Function.apply(object, [arg1,arg2,...])
Function.bind(object, arg1, arg2,...)
Same point
You can change the point of this, and the first parameter is the object this will point to.
difference
Call and apply will automatically execute functions when they are used, but bind will not.
Can you manually implement the three methods yourself?
bind method
concept of returns a copy of the original function (also called the binding function), and sets the this
keyword to the provided value when calling. And when calling the new function, take the given parameter list as the first several items of the original function's parameter sequence.
function.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg
: The value passed to the target functionthis
parameter when calling the binding function. If thenew
operator is used to construct the binding function, this value is ignored. Whenbind
insetTimeout
when creating a function (provided as a callback), asthisArg
any original value passed will be converted toobject
. If the parameter list of thebind
this
execution scope will be regarded as thethisArg
new function.arg1, arg2, ...
: When the target function is called, the parameters are added to the parameter list of the bound function in advance.
example of
window.value = 3;
var foo = {
value:1
};
function bar() {
console.log(this.value);
}
bar(); // 3
bar.call(foo); //1
//指定函数this绑定为foo, 产生一个新函数,之后再运行的时候,内部的this就是被绑定的对象
var bindFoo = bar.bind(foo);
setTimeout( function() {
bindFoo();
},2000)
// 2秒后打印 1
This example can well understand the application of bind
bar()
directly calls the function, wherevalue
refers to all variablesvalue = 3
bar.call(foo)
here usescall
immediately change thebar
inthis
tofoo
bind
often used for asynchronous. InsetTimeout
bar
ofthis
keeps pointing tofoo
within the set time, so it will print 1 instead of 3 after two seconds.
pre-knowledge:
MDN: The binding function can also be constructed using the new operator, and it will behave as if the target function has been constructed. The provided this value will be ignored, but the preceding parameters will still be provided to the simulation function.
Special note: After the binding function is new
, it needs to inherit the prototype chain method of the original function, and the this provided during the binding process is ignored (inheriting the this object of the original function), but the parameter will still use
code implementation
const wang = {
age: 18,
love: 'coding',
hello: function (age, love) {
if (age) this.age = age;
if (love) this.love = love;
console.log("hello world, i am ghostwang," + this.age + "," + this.love);
}
};
const ye = {
age: 19,
love: 'sleeping'
};
// wang.hello.myCall(ye, 0);
Function.prototype.myBind = function () {
if (typeof this !== 'function') {
throw new TypeError(this + 'must be a function');
}
const target = Array.from(arguments)[0]; // 第一个参数是this
const args = Array.from(arguments).slice(1);
const self = this;
let fBound = function () {
const _this = this instanceof self ? this : target; // 检测是否使用new创建
return self.apply(_this, args);
}
/** 假设我们将调用bind的函数称为C,
将fBound的prototype原型对象指向C的prototype原型对象(上例中就是self),
这样的话如果将fBound作为构造函数(使用new操作符)实例化一个对象,
那么这个对象也是C的实例,this instanceof self就会返回true。
这时就将self指向新创建的对象的this上就可以达到原生bind的效果了(不再固定指定的this)。
否则,才使用oThis,即绑定指定的this。**/
if (this.prototype) {
fBound.prototype = this.prototype
}
return fBound;
}
const foo = wang.hello.myBind(ye);
const foo2 = wang.hello.myBind(ye, 10, 'mom love u');
const nFoo = new foo2(); // hello world, i am ghostwang,10,mom love u
foo(); // hello world, i am ghostwang,19,sleeping
call method
Concept: function.call(thisArg, arg1, arg2, ...)
;
thisArg
: The valuethis
specified when the fun Note that the specifiedthis
value is not necessarily true when the function is executedthis
value, if the function is in the lower non-strict mode, designated asnull
andundefined
ofthis
value will automatically point to the global object (this
, which is the original value (number, string, Boolean value), will point to the automatic packaging object of the original value.arg1, arg2, ...
: The specified parameter list.
var obj = { name:'segmentfault' };
function fn() {
// console.log(this);
console.log(this.name);
}
fn(); // undefined
fn.call(obj); // segmentfault
Understand: First, look for call
method, by looking for the prototype chain, in Function.prototype
find on call
method; then, change fn
function of this
point, will fn
execution.
var obj = { name:'wc' };
function fn(age, country) {
console.log(this.name + '-' + age + '-' + country);
}
fn.call(obj, 18, 'China'); // wc-19-China
Understanding: With parameters passed in, the parameters need to be expanded. This is the only apply
method.
code implementation
Function.prototype.myCall = function () {
const argumentsArr = Array.from(arguments);
const target = argumentsArr[0];
if (!target) { // 判断是node还是浏览器环境
target = typeof window === undefined ? global : window;
}
target.fn = this; // 这里的this指向的是.前面的对象,也就是被调用的函数的原型对象
// 现在taget的fn属性就是缓存了被调用的函数, 需要改变这个函数的内部this,.前面是谁,this就指向谁,所以现在this是taget
const res = target.fn(argumentsArr.slice(1));
delete target.fn;
return res;
}
const wang = {
age: 18,
love: 'coding',
hello: function () {
console.log("hello world, i am zhou," + this.age + "," + this.love);
}
};
const ye = {
age: 19,
love: 'sleeping'
};
wang.hello.myCall(ye); // hello world, i am ghostwang,19,sleeping
summary:
- The first parameter of the
call
method is used to change the function that calls thecall
this
points to , but if the value ofnull/undefined
this
will point towindow
call
method needs to pass the actual parameters in according to the number of formal parameterscall
last method uses parameters to performcall
function in vivothis
points to function, generally point to callcall
function
apply method
Concept: a call having a given this
function value, as well as an array (or similar array of objects parameters) supplied.
func.apply(thisArg, [argsArray])
thisArg
: Optional. The valuethis
used when the functionfunc
Please note thatthis
may not be the actual value seen by this method: if this function is in non-strict mode, when it is specified asnull
orundefined
, it will automatically be replaced with a pointer to the global object, and the original value will be wrapped.argsArray
: Optional. An array or array-like object in which the array elements will be passed as separate parameters to thefunc
function. If the value of this parameter isnull
orundefined
, it means that no parameters need to be passed in.
code implementation
const wang = {
age: 18,
love: 'coding',
hello: function () {
console.log("hello world, i am zhou," + this.age + "," + this.love);
}
};
const ye = {
age: 19,
love: 'sleeping'
};
Function.prototype.myApply = function () {
const argumentsArr = Array.from(arguments);
const target = argumentsArr[0];
if (!target) { // 判断是node还是浏览器环境
target = typeof window === undefined ? global : window;
}
target.fn = this; // 这里的this指向的是.前面的对象,也就是被调用的函数的原型对象
// 现在taget的fn属性就是缓存了被调用的函数, 需要改变这个函数的内部this,.前面是谁,this就指向谁,所以现在this是taget
const res = target.fn(...argumentsArr.slice(1));
delete target.fn;
return res;
}
wang.hello.myApply(ye); // hello world, i am zhou,19,sleeping
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。