apply,call ,bind的区别及用法

一、相同点

  1. 作用都是在函数执行时,动态改变函数的运行环境(执行上下文)
  2. 第一个参数都是改变运行环境的对象,改变this的指向
  3. 如第一参数为null,函数体内的this会指向默认的宿主对象,即window

二、不同点

  1. apply: 第二个参数是数组,数组的每一个成员会依次传递给调用函数
    例:B.apply(A, arguments);即A对象调用B对象的方法(改变函数B内的this的值为A)

  2. call:从第二个参数开始,每一个参数会依次传递给调用函数
    例:B.call(A, args1,args2);即A对象调用B对象的方法。

  3. bind:除了返回是函数以外,其参数与call一样。

三、用途

  1. 改变this的指向,扩充函数赖以运行的作用域,对象不需要与方法有任何耦合关系

例1:

window.color = 'red';
var o = {color:'blue'};
function sayColor() {
    alert(this.color);
}
sayColor();   //red
sayColor.call(this);   //red
sayColor.call(window);   //red
sayColor.call(o);    //blue

例2:在事件内部调用func函数时,func函数体内的this就指向了window,不是div

document.getElementById("div1").onclick=function(){
    console.log(this.id);  //div1
    var func=function(){
        console.log(this.id);  //undefined
    }
	func();
}

使用call来修正this的场景:

document.getElementById("div1").onclick=function(){
    var func=function(){
        console.log(this.id);  //div1
    };
    func.call(this);
}
  1. Function.prototype.bind:指定函数内部的this指向
Function.prototype.bind=function(context){  //context为我们想修正的this对象
    var self=this;  //保存原函数func
    return function(){  //返回一个新函数,实际上执行时会先执行这个新函数
        return self.apply(context,arguments);  //执行原来的func函数,指定context为func函数体内的this
    }
};
var obj={
    name:"yian"
};
var func=function(){
    console.log(this, name);  //yian
}.bind(obj);
func();

往func函数中预先填入参数:

Function.prototype.bind=function(){
    var self=this,  //保存原函数func
            context=[ ].shift.call(arguments),  //需要绑定的this上下文
            args=[ ].slice.call(arguments);  //剩余的参数转成数组
    return function(){  //返回一个新数组
        return self.apply(context,[ ].concat.call(args,[ ].slice.call(arguments)));
        //执行新函数时,会将之前传入的context当作新函数体内的this
        //并将组合两次分别传入的参数,作为新函数的参数
    }
};
var obj={
    name:"yian"
};
var func=function(a,b,c,d){
    console.log(this.name);  //yian
    console.log([a, b, c, d]);  //[1,2,3,4]
}.bind(obj,1,2);
func(3,4);
  1. 借用其他对象的方法

第一种:借用构造函数

var A=function(name){
    this.name=name;
};
var B=function(){
    A.apply(this,arguments);
};
B.prototype.getName=function(){
    return this.name;
};
var b=new B();
b.name=”yian”;
console.log(b.getName());  //yian

第二种:操作arguments时,需要找Array.prototype对象借用方法
(原因:函数的参数列表arguments是一个类数组对象,虽然它有下标,但它并非真正的数组,所以不能像数组一样,进行排序操作或往集合里添加一个新的元素)

(1)Array.prototype.push:往arguments中添加一个新元素

(function(){
    Array.prototype.push.call(arguments,3);
    console.log(arguments);  //[1,2,3]
})(1,2);

(2)Array.prototype.slice:把arguments转成真正的数组
(3)Array.prototype.shift:截去arguments列表中的头一个元素

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值