JavaScript的this
this
首先,说下this
的两个常见误区
指向自身?
因为this
的从英文的角度上,很容易给人自身感觉,导致出this
指向函数自身的想法。
function foo(){
var a = 4;
console.log(this.a); // undefined
console.log(this.b); // undefined
console.log(foo.b);; // 1
}
foo.b = 1;
foo()
很明显,this
并不是指向函数自身的,this.b
和foo.b
并不是同一个
this指向与函数的作用域有关?
function foo(){
var a = 4;
function baz(){
console.log(a); // 4
console.log(this.a); // undefined
}
baz()
}
foo()
试图用作用域链的方法查找a,然而this
并不买账。
那么接下来开始真正介绍this
this的绑定规则
this的绑定要判断用了什么规则,总共有四条。
默认绑定
默认绑定就是this指向window
var a = 4;
function foo(){
this.bar();
}
function bar() {
console.log(this.a) // 4
console.log(window.a) // 4
}
foo()
正是因为this指向window,而bar和a又刚好作为window的属性,所以可以访问
当其他规则无法适用时,就会绑定到window
隐式绑定
如果函数作为某个对象的属性,那么this
就会指向这个对象
var a = 4;
function foo(){
this.bar(); // 2
console.log(this.a); // 1
}
var obj = {
a: 1,
bar: function(){
console.log(2)
},
foo
}
obj.foo()
从这也可以看出,隐式绑定的优先级要高于默认绑定
丢失绑定
隐式绑定如果操作不当,会导致绑定丢失
var a = 4;
function foo(){
//this.bar(); 报错,this指向window,但window没有bar函数
console.log(this.a); // 4
}
var obj = {
a: 1,
bar: function(){
console.log(2)
},
foo
}
var baz = obj.foo;
baz()
这种情况下,将对象里的函数赋值给一个变量baz,所以baz是foo的引用,但是它引用的是foo本身,并不是obj里的foo,所以这时候的this就指向了window
显示绑定
通过call()
和apply()
来改变this的指向
var a = 4;
function foo(){
console.log(this.a); // 1
}
var obj = {
a: 1
}
var obj1 = {
a: 2
}
function baz() {
foo.call(obj1); // 2
}
function bar(){
foo.call(obj)
}
bar(); // 1
baz()
foo(); // 4
foo.call(this要绑定到的对象)
,通过this.call
就可以指定this的对象了,不过这里要注意的是,并不是绑定后,foo的this就到指定的对象了,只有在执行这段代码foo.call()
的时候,this才发生改变,最后一行代码,单独调用了foo
,this依然指向window。
new绑定
使用new来调用函数,或者说发生构造函数调用时,会自动执行下面的操作
- 创建一个全新的对象
- 这个新对象会被执行
[[Prototype]]
连接 - 这个新对象会绑定到函数调用的this
- 如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象
function foo(a){
this.a = a;
this.baz = function(){
console.log('hellow'+ a)
}
}
var bar = new foo(2);
console.log(bar.a)
bar.baz();
这时this就指向了new出来的实例了