call、apply、bind方法详解

call, apply, bind 三者作用都是改变this指向。

bind与apply、call的区别:

  • bind返回一个函数,可以延迟调用。
var name = 'window';
var newThis = { name: 'newThis' };
function showName(info1, info2) {
    console.log(this.name, info1, info2);
}
showName('a', 'b'); //输出:window a b

// 通过bind改变this指向
var newShowName = showName.bind(newThis, 'hello', 'world');
newShowName(); //输出:newThis hello world
  • apply、call直接调用

apply与call的区别在于接受参数的方式不一样。

  • call可以接收多个参数,第一个参数是this(你想指定的上下文),在调用的时候需要把其他参数一个一个按顺序传入
var name = 'window';
var newThis = { name: 'newThis' };
function showName(info1, info2) {
    console.log(this.name, info1, info2);
}
showName('a', 'b'); //输出:window a b
//通过call改变this指向
showName.call(newThis, 'hello', 'world'); //输出:newThis hello world
  • apply只能接收两个参数,第一个参数是this(你想指定的上下文),第二个参数是一个数组,在调用的时候需要把其他参数都放在这个数组里。
var name = 'window';
var newThis = { name: 'newThis' };
function showName(info1, info2) {
    console.log(this.name, info1, info2);
}
showName('a', 'b'); //输出:window a b
//通过apply改变this指向
showName.apply(newThis, ['hello', 'world']); //输出:newThis hello world

bind

bind 会返回一个函数,可以在之后任意时间调用。

bind传递参数问题:
在通过bind改变this指向的时候所传入的参数会拼接在调用返回函数所传参数之前,多余参数不起作用。

var newShowName = showName.bind(newThis, 'hello');
//在通过bind改变this指向的时候只传了“hello”一个参数,
//在调用newShowName这个返回参数的时候,bind传参拼接在其前
newShowName('world'); //输出:newThis hello world
var newShowName = showName.bind(newThis, 'hello');
//在通过bind改变this指向的时候只传了“hello”一个参数,
//在调用newShowName这个返回参数的时候,bind传参拼接在其前,
//这时newShowName的参数为“hello”,“a”,“world”
//而该函数只需要两个参数,则第三个参数被忽略
 newShowName('a','world'); //输出:newThis hello a

bind传入的参数和newShowName方法传入的参数会拼接在一起,一齐传给showName方法。

bind无法改变构造函数的this指向

var name = 'window';
var newThis = { name: 'newThis' };
function showName(info1, info2) {
    console.log(this.name, info1, info2);
}
showName('a', 'b'); //输出:window a b

// 通过bind改变this指向
var newShowName = showName.bind(newThis, 'hello','1','2');
newShowName('a','world'); //输出:newThis hello world

console.log(new newShowName().constructor); //输出:showName函数体

可以看出,通过bind改变this指向返回函数的构造器还是最开始的showName函数。
new newShowName()实例化了一个新的方法,这个方法的this也不再指向newThis。

通过apply模拟bind源码实现:

Function.prototype.newBind = function(target){
    var self = this; //self是调用newBind的方法
    var args = [].slice.call(arguments, 1);
    var temp = function () {};
    var f = function () {
        var _arg = [].slice.call(arguments, 0);
        return self.apply(this instanceof temp?this:target||window, args.concat(_arg));
    };
    temp.prototype = self.prototype;
    f.prototype = new temp();
    return f;
};
  • 6
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值