• JavaScript 中的 apply、call、bind


    一、常规

    在 JavaScript 中,apply、call、bind 是三个与函数调用相关的方法,它们都允许你在调用函数时手动设置函数的上下文(即 this 指向)。

    1、apply 方法:apply 方法允许你调用一个函数,并且手动设置函数的上下文(即 this 指向)以及传递一个参数数组。其语法如下:

    function.apply(thisArg, [argsArray])

    其中,thisArg 表示函数要绑定的上下文,argsArray 是一个可选的数组,其中包含将传递给函数的参数列表。

    例如,以下代码会将数组 [1, 2, 3] 作为参数传递给函数 foo,并且将函数的上下文设置为对象 obj:

    function foo(a, b, c) {
      console.log(a + b + c);
    }
    
    var obj = {
      x: 1,
      y: 2,
      z: 3
    };
    
    foo.apply(obj, [1, 2, 3]); // 输出 6

    2、call 方法:call 方法与 apply 方法类似,也是允许你调用一个函数,并且手动设置函数的上下文(即 this 指向),但是它需要你手动传递一个参数列表,而不是一个参数数组。其语法如下:

    function.call(thisArg, arg1, arg2, ...)

    其中,thisArg 表示函数要绑定的上下文,arg1、arg2、... 是将传递给函数的参数列表。

    例如,以下代码会将参数 1、2、3 传递给函数 foo,并且将函数的上下文设置为对象 obj:

    function foo(a, b, c) {
      console.log(a + b + c);
    }
    
    var obj = {
      x: 1,
      y: 2,
      z: 3
    };
    
    foo.call(obj, 1, 2, 3); // 输出 6

    3、bind 方法:bind 方法与 apply、call 方法不同,它并不会立即调用函数,而是会返回一个新的函数,并且这个新函数的上下文(即 this 指向)被永久地绑定到了指定的对象上。其语法如下:

    function.bind(thisArg, arg1, arg2, ...)

    其中,thisArg 表示函数要绑定的上下文,arg1、arg2、... 是一些可选的参数,这些参数将在调用新函数时作为参数列表传递给原函数。

    例如,以下代码会将函数 foo 的上下文绑定到对象 obj 上,并返回一个新函数 newFoo,当调用 newFoo 时,它的参数将被传递给原函数 foo:

    function foo(a, b, c) {
      console.log(a + b + c + this.x + this.y + this.z);
    }
    
    var obj = {
      x: 1,
      y: 2,
      z: 3
    };
    
    var newFoo = foo.bind(obj, 1, 2, 3);
    newFoo(); // 输出 12

     

    下面是一个示例,演示了使用 apply、call、bind 方法的一些特性:

    function foo(a, b) {
      console.log(this.x + this.y + a + b);
    }
    
    var obj1 = {
      x: 1,
      y: 2
    };
    
    var obj2 = {
      x: 3,
      y: 4
    };
    
    // 使用 apply 方法调用函数 foo,并将 obj1 作为上下文
    foo.apply(obj1, [3, 4]); // 输出 10
    
    // 使用 call 方法调用函数 foo,并将 obj2 作为上下文
    foo.call(obj2, 5, 6); // 输出 18
    
    // 使用 bind 方法绑定函数 foo 的上下文为 obj1,并创建一个新函数 newFoo
    var newFoo = foo.bind(obj1, 7);
    newFoo(8); // 输出 18
    
    // 使用 bind 方法绑定函数 foo 的上下文为 obj2,并创建一个新函数 newFoo2
    var newFoo2 = foo.bind(obj2);
    newFoo2(9, 10); // 输出 26

    二、特殊

    1、如果在使用 applycallbind 方法时没有传递 thisArg 参数或者传递了 nullundefined,那么默认的上下文将是全局对象(在浏览器环境中,通常是 window 对象)。

    function foo() {
      console.log(this === window); // 在浏览器环境中,输出 true
    }
    
    // 使用 apply 方法调用函数 foo,没有传递 thisArg 参数
    foo.apply(); // 输出 true
    
    // 使用 call 方法调用函数 foo,传递了 null 作为 thisArg 参数
    foo.call(null); // 输出 true
    
    // 使用 bind 方法绑定函数 foo 的上下文为 null,并创建一个新函数 newFoo
    var newFoo = foo.bind(null);
    newFoo(); // 输出 true

    2、如果使用 bind 方法绑定了函数的上下文后,再使用 applycall 方法调用这个函数,那么绑定的上下文将会被忽略,仍然使用传递给 bind 方法的上下文。

    var obj1 = {
      x: 1,
      y: 2
    };
    
    var obj2 = {
      x: 3,
      y: 4
    };
    
    function foo() {
      console.log(this.x + this.y);
    }
    
    // 使用 bind 方法绑定函数 foo 的上下文为 obj1,并创建一个新函数 newFoo
    var newFoo = foo.bind(obj1);
    
    // 使用 apply 方法调用新函数 newFoo,并将 obj2 作为上下文
    newFoo.apply(obj2); // 输出 3
    
    // 使用 call 方法调用新函数 newFoo,并将 obj2 作为上下文
    newFoo.call(obj2); // 输出 3

    在这个示例中,先使用 bind 方法将函数 foo 的上下文绑定为 obj1,并创建了一个新函数 newFoo。然后,分别使用 applycall 方法调用新函数 newFoo,并将 obj2 作为上下文。由于使用了 bind 方法绑定了上下文,无论传递了什么参数,都不会改变绑定的上下文。这就是绑定的上下文被忽略的情况。最终输出的结果为 3,而不是 7。

    3、如果使用 bind 方法绑定了函数的上下文后,再使用 new 操作符创建实例,那么绑定的上下文将被忽略,而是创建一个新的对象作为 this,并且原函数中的 this 将会指向这个新对象。

    function Foo() {
        console.log(this.x + this.y);
    }
    
    var obj = {
        x: 3,
        y: 4
    };
    
    // 使用 bind 方法绑定函数 Foo 的上下文为 obj,并创建一个新函数 NewFoo
    var NewFoo = Foo.bind(obj);
    NewFoo();   // 输出 7
    
    // 使用 new 操作符创建实例,此时会忽略绑定的上下文 obj,而是创建一个新对象作为 this
    var newObj = new NewFoo();  // 输出 NaN
    
    console.log(newObj.x); // 输出 undefined
    console.log(newObj.y); // 输出 undefined

    在这个示例中,先使用 bind 方法将函数 Foo 的上下文绑定为 obj,并创建了一个新函数 NewFoo。然后,使用 new 操作符创建实例,此时会忽略绑定的上下文 obj,而是创建一个新对象newObj作为 Foo 函数的 this 上下文。因此,Foo 函数中的 this 指向了新创建的对象 newObj,新对象 newObj 继承了Foo 函数中定义的属性,但属性 x 和 y 并未定义,因此输出 undefined

     

    在 JavaScript 中,函数可以被视为构造函数,并且可以使用 new 关键字来创建实例。

     

    综上所述,apply、call、bind 方法都是用于手动设置函数的上下文(即 this 指向),在实际开发中也经常被使用。对于这三个方法,需要了解它们的使用方法、语法和一些注意事项,以便在开发中更加灵活地使用它们。

     

  • 相关阅读:
    Nestjs开发环境和生产环境的配置
    SpringBoot项目使用hutool工具进行HttpClient接口调用的处理(文件上传)
    BOT模块论文阅读
    接口测试入门实践
    C++ json-cpp库的基本使用方法
    SpringCloudAlibaba实战入门之手把手教你创建第一个SpringCloudAlibaba项目(三)
    应用在手机触摸屏中的电容式触摸芯片
    为什么重写equals方法,还必须要重写hashcode方法,重写equals()和hashCode()方法实例
    sftp上传下载文件实现
    《机器学习实战》4.朴素贝叶斯
  • 原文地址:https://www.cnblogs.com/yuzhihui/p/17147218.html