call,apply和bind详解

本来这些内容是写在this指向那篇博客中的,但发现面试笔试中这个知识点出现的几率很高,所单独拿出来讲解一下。

一.call和apply

call和apply其实是同一个东西,区别只有参数不同,call是apply的语法糖,所以就放在一起说了,这两个方法都是定义在函数对象的原型上的(Function.prototype),call和apply方法的作用都是改变函数的执行环境,第一个参数传入上下文执行环境,然后传入函数执行所需的参数。传入call的参数只能是单个参数,不能是数组。apply可传入数组。话不多说直接上代码,看下面的例子:

1.

function ga() {
    let x=1;
    function gb(y) {
        return x+y;
    }
}
gb(2)  //调用发生报错,因为拿不到x的值
gb.call(ga,2);   //使gb在ga环境中执行,可以拿到x,运行正常

 上面的代码中由于gb()函数执行依赖于ga()中的变量,所以我们使用了call将gb的运行环境变成了ga。

2.

function gg(x,y,z){
    let a=Array.prototype.slice.call(arguments,1,2) //通过slice方法获取到了第二个参数
    return a; //返回[2]
}
gg(1,2,3)

 arguments是一个类数组对象,它本身不能调用数组的slice方法,使用call将执行slice方法的对象由数组变为了arguments。

3.

我们可以使用apply来改写上面的代码,传入一个数组。

function gg(x,y,z){
    let d=[1,2]
    let a=Array.prototype.slice.apply(arguments,d) //通过slice方法获取到了第二个参数
    return a; //返回[2]
}
gg(1,2,3)

 4.

我们还可以使用apply和call实现继承。

function Parent(name)
    {
        this.name = name;
        this.sayHello = function()
        {
            alert(name);
        }
    }

    function Child(name)
    {
       //子类的this传给父类
        Parent.call(this, name);
    }

    var parent = new Parent("张三");
    var child = new Child("李四");

    parent.sayHello();
    child.sayHello();

二. bind

bind和apply区别是apply会立刻执行,而bind只是起一个绑定执行上下文的作用。看下面的例子:

function ga() {
    let x=1;
    (function gb(y) {
        return x+y;
    }).bind(this)  //使用bind将gb函数的执行上下文绑定到ga上
}
gb(2)  //运行正常,得到3

有些情况下为了方便我们可以直接将ga绑定,而不用在调用的时候再使用apply。

猜你喜欢

转载自blog.csdn.net/qq_41635167/article/details/83307357