JavaScrip 里面的 this 到底指向哪里?它是一个很特别的关键字,被自动定义在所有函数的作用域中,是 JavaScrip 的一种上下文机制
通常我们会以为 this 是指向函数或对象自己,但事实并非如此,this 实际上是在函数被调用时发生的一个绑定,它指向什么完全取决于函数在哪里被调用,并非我们一开始所想的那样,我们可以看下下面的例子:
-
指向一个对象:
function foo() { //输出this里面的a的值 console.log(this.a) } var targer = { a: 2, foo: foo } //这时候 foo 里面的 this 指向了targer targer.foo() // 2 8
-
在独立函数里面,指向全局(非严格模式下):
var name = "my name" function foo() { console.log(this.name) } //非严格模式,this指向全局 foo()// my name
-
new 的时候,指向创建的对象:
function foo(a) { this.a = a; } var target = new foo(999); console.log(target.a); // 999
也正是因为 this 这个特性,JavaScrip 提供了 call、apply 和 bind 这 3 个方法来改变 this 的指向,这个也叫做 this 的显式绑定,现在我们来看下它们到底有哪些区别:
call 方法可以传入另外一个对象来让函数内的 this 绑定指向,并立即执行函数:
function foo(obj) { console.log(this.android + ":" + obj); } var target = { android: 0 }; //this 绑定 target //执行函数 foo.call(target, 9); // 0:9
apply 方法作用和 call 方法是一样的,它们的不同之处在于 apply 在传入调用函数的参数时,它需要接收一个数组对象:
function foo(one, two) { console.log(this.android + ":[" + one + "-" + two + "]"); } function bar(...obj) { console.log(this.android + ":[" + obj + "]"); } var target = { android: 1 }; //this 绑定 target //执行函数 foo.apply(target, [2, 0]); // 1:[2-0] bar.apply(target, [1, 0]); // 1:[1,0]
看起来 apply 不如 call 方法好用,但是如果遇到类似上面的 bar 这种有着不定参数列表的函数就只能使用 apply 方法了
bind 方法与 apply 和 call 很相似,也是可以改变函数体内 this 的指向,但是它并不会立即调用函数,而是返回一个称为绑定函数的新函数:
function foo(obj) { console.log(this.android + ":" + obj); } var target = { android: 1 }; //this 绑定 target //返回绑定了this 的新函数 foo = foo.bind(target); foo(9) // 1:9