bind 定义
来源于mdn
bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被bind的第一个参数指定,其余的参数将作为新函数的参数供调用时使用。
输入
fn.bind(thisArg,arg1,arg2,...)
- 第一个参数为绑定的this指向。
- 其余的参数为。当目标函数被调用时,预先添加到绑定函数的参数列表中的参数。
输出
返回一个原函数的拷贝,并拥有指定的this值和初始参数。
测试
- 一个函数(原函数,他里的this会被改变)
- 一个对象 (this指向的目标对象)
bind实现-方法一(es6版)
- 第一步,保存原调用函数this。
- 参数的截取,不多说了
- 返回一个函数,这是bind的特性。
- 返回函数中通过apply调用,做一个父函数,子函数的参数连接即可。
- 为何要连接参数,是因为,调用的时候,参数传给第一个函数和返回函数都可以。
Function.prototype.myBind=function(){
var me = this; // 保存原调用函数
var args=[...arguments];
var context = args.shift();
return function(){
//console.log(context,args,arguments);
me.apply(context,[...args,...arguments])
};
};
function A(x,y){
console.log(this.b+" "+x+" "+y);
//return this.b+" "+x+" "+y;
};
var B={b:1};
A.myBind(B,2)(3);//1 2 3
bind实现-方法一(es5版)
些方法特点是,多处借用Array原型上的方法处理伪数组arguments。
Function.prototype.myBind=function(){
var me = this; // 保存原调用函数
// 取改变后的this
var context = Array.prototype.shift.call(arguments);
// 取第一个参数外的剩余参数,把arguments转为数组
var args = Array.prototype.slice.call(arguments);
// bind的特点返回一个函数
return function(){
var args2 = Array.prototype.slice.call(arguments);
//参数拼接
var allArgs = Array.prototype.concat.call(args,args2);
me.apply(context,allArgs);
}
};
function A(x,y){
console.log(this.b+" "+x+" "+y);
//return this.b+" "+x+" "+y;
};
var B={b:1};
A.myBind(B,2)(3); // 1 2 3
小提示
在arguments的处理上。call或者apply是用来改变函数执行是this指向的,这里以argumens对象为this来执行Array.prototype.slice函数,而Array.prototype.slice函数不带参数时默认返回的是数组对象本身。
Array.prototype.shift.call(arguments);和arguments[0]的功能看上去是一样的。但是shift改变了原始数据。所以,更方便。不过现在都用...了
slice()不传参数的复制功能很常用。
var a=[1,2,3];
var b = a.slice();
b;//[1, 2, 3]
a==b;//false
bind 小结
你调用我,我不一定会执行。
- bind 函数的特点是:你调用我,我不直接执行,而是间接在函数内部在调用自己而进行执行。
- 试想,如果,bind 中不进行原函数的调用。那么,bind的执行。可以什么也不做。但是bind的功能就是调用的时候,改变this。还是你调用他的原函数。然后把this,指向他的第一个参数。
- 试想,函数A的调用。可能就是函数B的调用。可能就是函数B和C的调用。可能调用了什么也没做。什么也没返回。这就是函数。一个伟大的发明。
call的定义,输入输出
call() 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法
输入
输出
实现一(对象属性赋值this。调用这个对象的属性)
Function.prototype.myCall = function(obj){
//console.log(obj);//改变的this指向,this指向A 然后obj.fn=A
//console.log(A);// 原调用函数
obj.fn = this;// 改变this指向为obj。此时obj.fn就是函数A
obj.fn([...arguments].slice(1));//改变this后,调用原函数A。
delete obj.fn;// 不能改变obj。把增加的fn属性删除
};
function A(arr){
console.log(this.b+arr[0]+arr[1])
};
var B={b:1};
A.myCall(B,2,3); //6
call实现小结
- 无论是call,apply,bind,调用原函数。改变this指向。处理参数。就这三件事。
- 上面的call方法 多打印一个undefined。后续我在看一下,今天先去实现脚手架。
apply的实现
与call不同的就是参数的处理上
Function.prototype.myApply = function(obj){
//console.log(obj);//改变的this指向
//console.log(A);// 原调用函数
obj.fn = this;// 改变this指向为obj。
obj.fn([...arguments[1]]);//改变this后,调用原函数。
delete obj.fn;// 不能改变obj。把增加的fn属性删除
};
function A(x,y){
console.log(this.b+" "+x+" "+y);
};
var B={b:1};
A.myApply(B,[2,3]); // 1 2 3
// 1 2,3 undefined
总结:
- 改变this指向:可以将原调用函数作为参数第一个对象(改变的this指向)的属性
- 参数不定长需要考虑,我们使用...,
- 我看网上有eval的实现版本,哈哈