首页 > 编程语言 >JavaScript 中的 apply、call、bind

JavaScript 中的 apply、call、bind

时间:2023-02-23 11:22:06浏览次数:38  
标签:上下文 函数 bind JavaScript call apply foo

在 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

 

除了以上的语法和使用方法之外,还有一些需要注意的点:

1、如果在使用 apply、call、bind 方法时没有传递 thisArg 参数或者传递了 null 或 undefined,那么默认的上下文将是全局对象(在浏览器环境中,通常是 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 方法绑定了函数的上下文后,再使用 apply 或 call 方法调用这个函数,那么绑定的上下文将会被忽略,仍然使用传递给 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。然后,分别使用 apply 和 call 方法调用新函数 newFoo,并将 obj2 作为上下文。由于使用了 bind 方法绑定了上下文,无论传递了什么参数,都不会改变绑定的上下文。这就是绑定的上下文被忽略的情况。最终输出的结果为 3,而不是 7。

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

function Foo() {
  this.x = 1;
  this.y = 2;
}

var obj = {
  x: 3,
  y: 4
};

// 使用 bind 方法绑定函数 Foo 的上下文为 obj,并创建一个新函数 NewFoo
var NewFoo = Foo.bind(obj);

// 使用 new 操作符创建实例,此时会忽略绑定的上下文 obj,而是创建一个新对象作为 this
var newObj = new NewFoo();

console.log(newObj.x); // 输出 1
console.log(newObj.y); // 输出 2

console.log(obj.x); // 输出 3
console.log(obj.y); // 输出 4

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

 

下面是一个示例,演示了使用 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

 

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

 

标签:上下文,函数,bind,JavaScript,call,apply,foo
From: https://www.cnblogs.com/yuzhihui/p/17147218.html

相关文章

  • JavaScript中止网络请求
    constcontroller=newAbortController();//1.创建AbortController实例constsignal=controller.signal;//2.创建信号fetch('/some/api',{signal})//3.......
  • JavaScript迭代协议解读
    JavaScript迭代协议解读迭代协议分为可迭代协议和迭代器协议。协议指约定俗成的一系列规则。可迭代协议可迭代协议规定了怎么样算是一个可迭代对象:可迭代对象或其原......
  • 【JS】JavaScript进阶 ES6 - 黑马视频笔记
    1.作用域作用域(scope)规定了变量能够被访问的“范围”,离开这个范围变量便不能被访问。分为:局部作用域、全局作用域。1.1局部作用域局部作用域分为:函数作用域、块作用......
  • 重学前端性能优化: requestAnimationFrame & requestIdleCallback All In One
    重学前端性能优化:requestAnimationFrame&requestIdleCallbackAllInOne微任务队列,CPU调度,时间分片requestAnimationFramecancelAnimationFramerequestIdleC......
  • 【JavaScript】JS引擎中执行上下文如何顺序执行代码
    首先我们知道JavaScript引擎包括一个调用栈和堆,调用栈是代码实际执行的地方,使用执行上下文(执行环境)来完成;堆是非结构化的内存池,存储了应用程序所需要的所有对象。执行上......
  • 创建多线程方式3:实现Callable接口 改造下载图片案例
    packagecom.Test;importorg.apache.commons.io.FileUtils;importjava.io.File;importjava.io.IOException;importjava.net.URL;importjava.util.concurrent.*;//开......
  • Javascript进阶
    Javascript进阶一.变量提升看以下代码,或多或少会有些问题的.functionfn(){console.log(name);varname='大马猴';}fn()发现问题了么.这么写代码,......
  • E005Web学习笔记-JavaScript(三):BOM
    一、简单学习DOM1、控制(增删改查)HTML文档的内容; 2、代码:获取页面的标签(元素)对象Element;document.getElementById();//通过元素的ID获取元素......
  • E006Web学习笔记-JavaScript(四):DOM
    一、概述1、简介DocumentObjectModel文档对象模型;将标记语言文档的各个部分,封装为对象,可以使用这些对象,对标记语言文档进行CRUD(增删改查)的动......
  • E007Web学习笔记-JavaScript(五):JS事件
    一、概述1、事件概念某些组件被执行了某些操作后,触发某些代码的执行;事件:某些操作,如点击,双击,鼠标移动,键盘按下……; 2、事件源组件,如按钮、文......