call,apply和bind的区别

134 阅读2分钟

前言

在面向对象的JavaScript中,一切皆对象,因此我们可以通过原型设置和访问函数和方法的附加属性

Call()

call()方法调用了一个带有this值的函数以及逐个提供参数,我们可以调用任何函数,并明确指定调用函数中应该引用的“this”。

let arg1 = {name:'John',age:20}
let arg2 = {name:'Marry',age:21}

function print(greeting1, greeting2){
    console.log(greeting1+` my name is ${this.name}, I'm ${this.age} years old, `+ greeting2)
}

print.call(arg1, 'Hello', 'Glad to meet you!')
//Hello my name is John, I'm 20 years old, Glad to meet you!

print.call(arg2, 'Hello', 'Glad to meet you!')
//Hello my name is Marry, I'm 21 years old, Glad to meet you!

Apply()

apply()方法调用一个函数并允许你传入一个数组参数。

let arg1 = {name:'John',age:20}
let arg2 = {name:'Marry',age:21}

function print(greeting1, greeting2){
    console.log(greeting1+` my name is ${this.name}, I'm ${this.age} years old, `+ greeting2)
}

print.apply(arg1, ['Hello', 'Glad to meet you!'])
//Hello my name is John, I'm 20 years old, Glad to meet you!

print.apply(arg2, ['Hello', 'Glad to meet you!'])
//Hello my name is Marry, I'm 21 years old, Glad to meet you!

Bind()

bind()方法返回一个新的函数,允许你传入一个数组参数或任意数量的参数。

let arg1 = {name:'John',age:20}
let arg2 = {name:'Marry',age:21}

function print(greeting1, greeting2){
    console.log(greeting1+` my name is ${this.name}, I'm ${this.age} years old, `+ greeting2)
}

let print1 = print.bind(arg1)
let print2 = print.bind(arg1)

print1('Hello', 'Glad to meet you!')
print2('Hello', 'Glad to meet you!')

当我们使用bind()方法的时候

  1. JS引擎正在创建一个新的print实例以及绑定arg1arg2作为this变量,所以本质上它复制了print这个函数

  2. 在创建一个print副本之后,我们可以调用print1print2函数,虽然它最初不在arg1arg2 对象上。但它现在将识别其属性和方法。

Call()和Apply()

call()apply()方法是可以互换的,两者都立即执行当前函数,需要决定是否更容易发送数组或逗号分隔的参数列表。而 bind() 创建一个新函数,它将 this 设置为传递给 bind() 的第一个参数。