【前置知识】

  • this

回顾this

  • 在全局环境里, this 始终指向全局对象。
  • 在函数内部, this 的取值取决于函数被调用的对象。

this 是JavaScript里难点之一,因为this 不能在执行期间被赋值,并且在每次函数被调用时 this 的值也可能会不同。

因此 this 的指向不明确,让人诟病!

为了让 this 指向明确,以下方法可以改变 this 指向。

  • 使用ES6的箭头函数
  • 使用applycallbing
  • new实例化一个对象

重点讲applycallbing

apply

apply() 方法调用一个函数, 其具有一个指定的this值,以及作为一个数组(或类似数组的对象)提供的参数

语法

  1. fun.apply(thisArg, [argsArray])
  • thisArg:在 fun 函数运行时指定的 this 值。
  • argsArray:一个数组或者类数组的对象
  • 如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。
  • 如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。

例子1:

  1. let obj = {
  2. name: '小明'
  3. }
  4. function func(firstName, lastName){
  5. console.log(firstName + ' ' + this.name + ' ' + lastName);
  6. }
  7. func.apply(obj, ['A','B']) //打印出 "A 小明 B"

call()

**call()** 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

语法:

  1. function.call(thisArg, arg1, arg2, ...)
  • thisArg:在 function 函数运行时使用的 this 值。
  • arg1, arg2, …:指定的参数列表。

thisArg的取值有以下4种情况:

  • 不传,或者传null,undefined, 函数中的this指向window对象。
  • 传递另一个函数的函数名,函数中的this指向这个函数的引用。
  • 传递字符串、数值或布尔类型等基础类型,函数中的this指向其对应的包装对象,如 String、Number、Boolean。
  • 传递一个对象,函数中的this指向这个对象。

例子2:
简单的 call() 使用

  1. let person = {
  2. name: "bens",
  3. sayHi(p1, p2) {
  4. console.log(p1 + p2 + ":" + this.name)
  5. }
  6. }
  7. //call和apply的唯一区别就是传参时apply是数组的形式.
  8. person.sayHi.call(person, "你", "是")

call() 和 apply() 区别

不同点:

  • apply 接受可包含多个参数的数组,而 call 接受的是包含若干个参数的参数列表。

共同点:

  • apply ( 同call )调用一个函数,第一个参数指定 this 值。
  • 定义:应用某一对象的一个方法,用另一个对象替换当前对象。
  • 为函数运行时的使用的 this 值,但使用的 this 值并不一定是该函数执行时的真正的 this 值。
  • 在非严格模式下,nullundefined 会自动替换成全局对象(浏览器里就是 window ),同时值为原始值(数字、字符串、布尔值)的 this 指向该原始值的包装对象。
  • 直接执行:
    1. function func() {
    2. console.log('linxin');
    3. }
    4. func.call(); // linxin
    这种方式直接 func() 也没什么区别。

bind()

**bind()** 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。 ———MDN

语法:

  1. function.bind(thisArg[, arg1[, arg2[, ...]]])

绑定this, 使得this不会被改变, 也可以绑定普通的参数

arg1, arg2, arg3…..:

  • 当目标函数被调用时,被预置入绑定函数的参数列表中的参数。

例子3:

  1. function f1(p1, p2) {
  2. console.log(this.name, p1, p2)
  3. }
  4. //f2等价于f1.call({name: "bens"}, "我是第一个参数, 我被绑定了")
  5. let f2 = f1.bind({ name: "bens",}, "我是第一个参数, 我被绑定了")
  6. f2("我是第二个参数, 只需要传我就可以, 其他都被绑定了")

总结

  • apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
  • apply 、 call 、bind 三者第一个参数都是this要指向的对象。
  • apply 、 call 、bind 三者都可以利用后续参数传参;
  • bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。

【资料来源】 JavaScript 中 apply 、call 的详解 javaScript 中 call、apply、bind的用法详解 深入浅出 妙用Javascript中apply、call、bind