JavaScript中的this
你真的了解this吗?
第一次写文章,如有错误还请指教。
很多人可能会对javascript中的this感到困惑,但其实this可能比你想象中的要简单ヽミ ´∀`ミノ<
开门见山
要真正的了解this,我们应该先去了解一下关于this的绑定机制。
this一共有四种绑定机制
- 默认绑定
- 上下文绑定
- new绑定
- 硬绑定
你可以把这四条规则看作this的天条,this到底代表了什么(也就是绑定了什么)和他们密切相关。
默认绑定
this默认绑定到javascript中windows全局对象。
除非该绑定被切断
function test() {
var a = 5
console.log(a)
}
var a = 10
test() //输出 10
是不是有点疑惑?我们再看一个代码片段
function test() {
var a = 5
console.log(a)
}
var a = 10
test() //输出 5
这个时候我们把this输出
function test() {
var a = 5
console.log(a)
console.log(this.a)
console.log(this)
//分别输出
// 5
// 10
// Window
}
var a = 10
test()
我们开始解释这3个输出:
console.log(a)
这个输出,其实没什么好疑惑的,是根据变量的作用域来获取到了function里的a的值console.log(this.a)
这里我们再看一次this的默认绑定
this默认绑定到javascript中windows全局对象。
而且在全局作用域中声明的变量默认绑定到windows,所以this.a指的就是var a = 10 在全局定义的那个a
而且第三个输出证实了这一点
this就是windows
注意在严格模式中,默认情况下this不会绑定到windows
同时我们得出了一个别的结论
this指向函数的作用域,这是一个天大的误解。
我们必须清楚this在任何的情况下都不指向函数的词法作用域
上下文绑定
理解上下文绑定主要注意是否是对象调用的函数
var obj = {
a: 2
}
obj是一个对象
function foo() {
console.log(this.a)
}
foo是一个声明的函数
而当一个函数属于一个对象的时候
obj.foo = foo
此时调用obj.foo()
输出 2
this在对象中的指向只会受到最后一层对象的影响
function foo() {
console.log(this.a)
}
var obj2 = {
a: 42,
foo: foo
}
var obj1 = {
a: 2,
obj2: obj2
}
obj1.obj2.foo()
//输出 42
所以关于上下文绑定一定要注意是否是对象调用的函数
上下文绑定会切断this的默认绑定
new绑定
使用new调用函数,或者说发生构造调用时,会自动执行下面的操作
- 创建一个全新的对象。
- 这个对象会被执行[[原型]]链接。
- 这个新对象会绑定到函数调用的this
- 如果这个函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。
function foo(a) {
this.a = a
}
var bar = new foo(2)
console.log(bar.a)
// 输出 2
使用new来调用foo(..)时,我们会构建一个新的对象并把它绑定到foo(..)调用的this上。
以上引用于 你不知道的javascript(上)
new绑定会切断默认绑定
硬绑定
通俗的说就是为function中出现的this手动的指定一个对象
javascript中提供了
call bind等常用的用于手动明确的指定this的函数
硬绑定也会切断默认绑定
总结
绑定的优先级
new绑定>硬绑定>上下文绑定>默认绑定
默认绑定是可以被另外三种绑定切断的
应用
判断this的方法:
1.函数是否在new中调用(new绑定)?
如果是的话this绑定的是新创建的对象。
var bar = new foo()
2.函数是否通过call,apply(显式绑定)或者硬绑定调用?
如果是的话。this绑定的是指定的对象。
var bar = new foo.call(obj2)
3.函数是否在某个上下文对象中调用(隐式绑定)?
如果是的话,this绑定的是那个上下文对象。
var bar = obj1.foo()
4.如果都不是的话,使用默认绑定。如果在严格模式下,
就绑定到undefined,否则绑定到全局对象。
var bar = foo()
本文结束,以上部分内容出自你不知道的javascript(上)