JavaScript----call,apply,bind

前言

callapplybind 是 JavaScript 中用于改变函数执行上下文(即 this 的指向)的方法。

call

在 JavaScript 中,call() 方法用于调用一个函数,并可以指定函数内部的 this 对象以及传递参数。

语法

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

特点和用途

  1. 更改函数的执行上下文:通过将一个对象作为第一个参数传递给 call() 方法,可以改变函数内部 this 的指向。原本函数中的 this 会被替换为 call() 方法中指定的对象。
   const person1 = { name: "张三" };
   const person2 = { name: "李四" };

   function greet() {
     console.log(`Hello, ${this.name}!`);
   }

   // 使用 call 更改执行上下文
   greet.call(person1); // 输出:"Hello, 张三!", greet()方法中的this指向 person1
   greet.call(person2); // 输出:"Hello, 李四!", greet()方法中的this指向 person2
  1. 传递参数:除了第一个用于指定 this 对象的参数外,后续的参数会作为被调用函数的参数进行传递。
function sum(a, b) {
   console.log(a + b)
   return a + b;
}

// 使用 call 传递额外参数
const result = sum.call(null, 1, 2); // 3, a = 1, b = 2
  1. 模拟继承:可以使用 call() 方法来模拟继承,创建一个新对象并继承另一个对象的属性和方法。
const parent = function (name) {
  this.name = name;
};
parent.prototype.greet = function () {
  console.log(`Hello, ${this.name}!`);
};

const child = function (name) {
  parent.call(this, name); // 调用父类构造函数
};
// 继承父类方法
child.prototype = Object.create(parent.prototype);

const childInstance = new child("张三");
childInstance.greet(); // 输出:"Hello, 张三!"

注意事项

  • call() 方法只会在函数执行时更改 this 的指向,不会永久绑定函数到指定的对象。
  • 对于箭头函数,call() 方法不能改变其 this 的指向,因为箭头函数的 this 是在定义时就确定的,并且基于其所在的词法环境。
  • 如果不传入第一个参数或传入 nullundefined,在非严格模式下,函数中的 this 会指向全局对象(在浏览器中是 window 对象);在严格模式下,this 的值则为 undefined

apply

在 JavaScript 中,apply()方法通常用于函数调用,并可以指定一个额外的参数作为函数体内的“this”对象。

语法

func.apply(thisArg, argsArray)
  • func:要调用的函数。
  • thisArg:指定函数运行时的 this 引用。如果该参数不是一个对象,那么它会被转换为对象。
  • argsArray:一个数组或类数组对象,包含要传递给函数的参数列表。

示例:

function sum(a, b) {
  return a + b;
}

var obj = { }; 
var result = sum.apply(obj, [2, 3]); 
// 这里将 obj 绑定为 sum 函数内部的 this 对象,[2, 3] 作为参数数组传递给 sum 函数
console.log(result); 

用途

  1. 改变函数的 this 上下文:可以将函数的 this 指向指定的对象。
function sayName() {
  console.log(this.name);
}

const person = { name: "张三" };

sayName.apply(person); // 输出: 张三

在上述示例中,通过 apply() 方法将 sayName() 函数的 this 指向了 person 对象。

  1. 传递参数列表:通过数组的形式来传递函数的参数。
function sum(a, b, c) {
  return a + b + c;
}

let nums = [11, 22, 33]; 
let result = sum.apply(null, nums); 
console.log(result); // 输出: 66

这里使用 apply() 方法将数组 nums 中的元素作为参数传递给 sum() 函数。

注意事项

  • 如果apply()方法的第二个参数不是一个有效的数组或者不是 arguments 对象,将会报错 TypeError
  • 对于箭头函数,call() 方法不能改变其 this 的指向,因为箭头函数的 this 是在定义时就确定的,并且基于其所在的词法环境。
  • 如果不传入第一个参数或传入 nullundefined,在非严格模式下,函数中的 this 会指向全局对象(在浏览器中是 window 对象);在严格模式下,this 的值则为 undefined

比较 apply和call

相同点
apply() 方法与 call() 方法非常类似,它们都可以改变函数的 this 对象并执行函数。

区别
apply() 接受的是一个参数数组,call() 方法接受的是一个参数列表。

示例:

function multiply(a, b) {
  return a * b;
}

let resultCall = multiply.call(null, 4, 6); 
let resultApply = multiply.apply(null, [4, 6]); 
console.log(resultCall); 
console.log(resultApply); 

bind

在 JavaScript 中,bind()方法用于创建一个新的函数,该函数在被调用时,其this值会被绑定到指定的对象,同时可以预设一些参数供调用时使用。

语法

let boundFunc = function.bind(thisArg, arg1, arg2,...)
  • thisArg:调用绑定函数时作为this参数传递给目标函数的值。如果使用new运算符构造绑定函数,则忽略该值。
    当在setTimeout中使用bind创建函数(作为回调提供)时,任何原始的thisArg值都会被转换为对象。如果bind函数的参数列表为空,或者thisArgnullundefined,执行作用域的this将被视为新函数的thisArg
  • arg1, arg2,...:当目标函数被调用时,这些参数会被预置入绑定函数的参数列表中。
  • boundFunc: 返回值,返回一个原函数的拷贝,并拥有指定的this值和初始参数。

用途

  1. 设置函数的执行上下文(this 指向):创建一个新函数,在调用这个新函数时,其this值会被指定为bind()方法的第一个参数。这使得函数可以在不同的上下文中执行,而不必担心this的指向问题。

示例:


    const person = {
      name: 'levi',
      greet: function() {
        console.log('hello,'+ this.name);
      }
    };
    // 直接调用 greet 方法,此时 this 指向 person 对象
    person.greet(); 
    // 保存 greet 方法的引用,但此时 this 不指向 person 对象
    let greetFunction = person.greet; 
    greetFunction(); 
    // 使用 bind 方法将 greetFunction 的 this 绑定到 person 对象
    let boundGreetFunction = greetFunction.bind(person); 
    boundGreetFunction(); 
    
const person = {
  firstname: 'John',
  lastname: 'Bob',
  getFullName: function() {
    console.log(this.firstname + "." + this.lastname);
  }
};
// 直接调用 getFullName 方法,此时 this 指向 person 对象
person.getFullName(); // John.Bob
 
// 保存 getFullName 方法的引用,但此时 this 不指向 person 对象
let getFullNameFunc = person.getFullName ; 
// getFullNameFunc();  // Error,TypeError: Cannot read properties of undefined (reading 'firstname')

// 使用 bind() 方法将 getFullNameFunc 函数的 this 绑定到 person 对象上
let boundGetFullNameFunc = getFullNameFunc.bind(person); 
boundGetFullNameFunc();  // John.Bob

这里的 printFullName.bind(person) 作为 printFullName 的“绑定的(bound)变体”,绑定了 this=person

  1. 预设参数:除了绑定this之外,还可以在bind()方法中预设一些参数。这些参数会在新函数调用时被使用,而后续传递给新函数的参数将依次排在预设参数之后。

示例:

function greet(greeting, punctuation) {
  console.log(greeting + ','+ this.name + punctuation);
}
const person = { name: 'levi' };
// 创建一个预设了参数的新函数 greetAlice
let greetAlice = greet.bind(person, 'hello'); 
greetAlice('!');  // hello,levi!
  1. 创建偏函数:可以固定部分参数,从而创建一个具有特定行为的新函数。

示例:

function sum(a, b) {
  console.log(a + b);
}

// 创建一个预设了参数的新函数 boundSum 
// sum 绑定this 为null, 绑定一个固定参数 1 ,返回一个新函数 boundSum 
let boundSum = sum.bind(null, 1)
console.log( boundSum (2) ); // 3
  1. 在特定环境中使用特定的 this 值:例如在事件处理程序中,确保函数中的this指向正确的对象。在一些框架(如 React)中,处理事件时经常会用到。
  2. 作为构造函数使用:当使用new操作符调用通过bind()绑定后的函数来创建实例时,原本通过bind()设置的this值会被忽略,但预设的参数仍然会生效。

apply、call和bind的区别

  1. 执行方式:
  • callapply会在调用时立即执行函数。
  • bind不会立即执行函数,而是返回一个绑定了新this的函数,稍后可以通过调用这个返回的函数来执行。
  1. 传参方式:
  • call的第一个参数是要绑定的this对象,后面可以逐个传入函数的参数。
  • apply的第一个参数是要绑定的this对象,第二个参数是一个数组,数组中的元素将作为函数的参数。
  • bind的传参方式与call类似,逐个传入参数,也可以在返回的函数调用时传入剩余参数。
  1. 修改this的性质:
  • callapply只是临时修改一次this的指向,即在调用它们的那次函数执行时改变this。当再次调用原函数时,this的指向还是原来的指向。
  • bind永久修改函数的this指向,它返回的新函数的this永远被改变了,且绑定后无法再修改
  • 16
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值