this
如果您正在学习 JavaScript,您可能已经了解到了 this
关键字。JavaScript 中的 this
关键字的行为与其他编程语言不同,这给不少程序员带来了困惑。
在其他面向对象编程语言中,this
关键字总是指向类的当前实例。而在 JavaScript 中,它的值取决于函数的调用方式。
我们来通过一些例子说明一下 JavaScript 中的 this
。
Example1
1 | const person = { |
此处因为我通过 person
对象来调用 printName
函数,所以 this
指向 person
对象。
我们在刚才的代码片段后面添加下面两行代码:
1 | const printFullName = person.printName; |
我们惊奇地发现打印结果是两个 undefined
。
原因是什么?
此处我们把 person.printName
的引用存储到了变量 printFullName
中。此后,我们调用它,且没有指明调用它的对象。这种情况下,this
会指向 window 或 undefined(严格模式下)。
因此会输出两个 undefined;若是在严格模式下则会报错。
Example 2
1 | const counter = { |
incrementCounter
中的 this
将会指向谁呢?
事实上,在上面的代码中,this 关键字会指向 event
对象,而不是 counter
对象。
根据前面所举的例子,我们可以发现函数中的 this
关键字指向根据函数的调用情况决定。有时候我们会一不小心丢失掉 this
。那么我们如何才能防止这种情况的发生呢?
call、bind、apply
我们知道在 JavaScript 中函数是一种特殊的对象,所以我们可以获取它的方法和属性。为了证明函数也是对象,我们可以做一些诸如下面这样的操作:
1 | function greeting() { |
JavaScript 也提供了一些特殊的方法和属性给每一个函数对象。所以 JavaScript 中的每个函数都继承了一些方法,其中就包括 call、apply、bind。
bind
bind 创建一个新的函数,并把 this 指向传入的对象。
语法为:
1 | function.bind(thisArg, arg1, arg2, ...) |
举个例子,假如我们有两个人物对象。
1 | const john = { |
我们可以使用 bind
方法来让 this
指向 john 和 jane 对象。
1 | const greetingJohn = greeting.bind(john); |
此处 greeting.bind(john)
创建了一个新的函数,且 this
指向了传入的 john 对象,接着把它赋值给了变量 greetingJohn
我们也可以使用 bind 来 DOM 操作的情况,比如:
1 | const counter = { |
在上面的例子中,this 会正确地指向 counter
对象而不是 event
对象。
注意:多次 bind()
是无效的,只会绑定到第一次调用的对象上
bind 接收多个参数
bind
可以接收多个参数。
例如:
1 | function greeting(lang) { |
在上面的例子中,我们把参数 en
传递给了 greeting
函数。
call
call
会将 this
指向对象,并立即执行。call
和 bind
的区别在于,call
会使函数立即执行,而 bind
会创建一个新的函数,不会马上执行。
语法:
1 | function.call(thisArg, arg1, arg2, ...) |
举个例子:
1 | function greeting() { |
上面例子我们可以看出 call
的结果是立即执行该函数。
call 接收多个参数
call
可以接收多个参数。
例如:
1 | function greet(greeting) { |
apply
apply
和 call
非常相像,不同之处在于 apply
的参数是一个数组,而 call
的参数是分散开的。
示例如下:
1 | function greet(greeting, lang) { |
原文:
https://blog.bitsrc.io/understanding-call-bind-and-apply-methods-in-javascript-33dbf3217be