前言
本文将从以下几方面论述 Javascript 中 this 的指向问题。
- 规范函数中,
this
的援用值是什么 - 箭头函数中,
this
的援用值是什么 - 应用
new
关键字创建对象时,this
的援用值是什么 - 闭包中应用
this
时,this
的援用值什么
规范函数中,this 的援用值是什么
规范函数中,this 援用的是把函数当成办法调用的上下文对象
在规范函数中 this
的值是会依据办法被调用的状况扭转所援用的值
window.identity = "The Window"
let object = {
identity: 'My Object',
getIdentityFunc() {console.log(this.identity)
}
}
object.getIdentityFunc() // My Object
const getIdentityFunc = object.getIdentityFunc
getIdentityFunc() // The Window
箭头函数中,this 的援用值是什么
在箭头函数中,this 援用的是定义箭头函数的上下文
由此能够看出箭头函数中的 this
援用值是固定的
window.identity = "The Window"
let object = {
identity: 'My Object',
testIdentity: this.identity,
getIdentityFunc:() => {console.log(this.identity)
}
}
console.log(object.testIdentity) // The Window
object.getIdentityFunc() // The Window
面试的时候我就遇到了这个问题,过后我心想
“在箭头函数中,this 援用的是定义箭头函数的上下文对象”
大家如果认真比拟这两句话能够发现我心里想的多了两个字 (或者说我就是囫囵的看了一遍书,基本没有好好的去了解、去验证),这两个字不多不少让我把this
的援用值认为成 object
这个对象了,所以我认为最初的后果应该是My Object
。
那么咱们当初来具体的看看这个定义箭头函数的上下文是什么呢?
在我看来,咱们能够把 this 值看成上下文
那 定义箭头函数的上下文 其实就是 object
的this
值呗;那咱们要晓得的其实就是 object
的this
的 identity
属性是什么呗?
在上方代码的倒数第二行就是为了阐明这个问题,因为属性 testIdentity
的值是 The Window
咱们能得出 object
的this
援用值其实是window
;
因为函数 getIdentityFunc
中的 this
援用值其实是 object
的this
,也就是 window
。所以函数getIdentityFunc
中的 this.identity
是The Window
。
既然箭头函数中的 this 是固定的,那么相似 call 的函数能扭转 this 的援用值吗
在 JS 中咱们能够应用 call
、apply
、bind
办法扭转 this
指向,既然箭头函数的 this
值援用值是固定的,那咱们能应用这几个办法扭转这个援用值吗?
看上面的代码
window.identity = "The Window"
let object = {
identity: 'My Object',
getIdentityFunc() {console.log(this.identity)
}
}
let object1 = {identity: 'My Object1'}
object.getIdentityFunc.call(object1) // My Object1
window.identity = "The Window"
let object = {
identity: 'My Object',
testIdentity: this.identity,
getIdentityFunc:() => {console.log(this.identity)
}
}
console.log(object.testIdentity) // The Window
object.getIdentityFunc() // The Window
object.getIdentityFunc.call(object) // The Window
比照这两处代码咱们能发现 call 办法根本无法扭转箭头函数的 this
的援用值。
应用 new 关键字创建对象时,this 的援用值是什么
在实例中 this 的援用值是以后所在的实例
window.identity = "The Window"
function Obj() {
this.identity = "My Object"
this.getIdentityFunc = function () {console.log(this.identity)
}
this.getIdentityFunc1 = () => {console.log(this.identity)
}
}
const obj = new Obj()
obj.getIdentityFunc() // My Object
obj.getIdentityFunc1() // My Object
咱们能够看到两个函数中输入的都是 My Object
,getIdentityFunc
函数的后果也之前调用的差异不大,因为在这个函数外面 this
的援用值仍然是 obj
这个上下文对象。
然而在函数 getIdentityFunc1
中,尽管都是箭头函数 (和第二个例子的代码做比拟),然而这一次的后果的确My Object
,也就是说这一次的this
援用值是对象obj
。
那么这个状况的起因是什么呢?咱们来回顾一下刚刚第二个例子外面箭头函数的 this
值是等于对象 object
的this
值,事实上这一次也是。所以造成这两次后果不同的起因其实是这两次的“函数上下文”不一样了。
- 第二个例子中
object
的函数上下文this
援用值是window
- 这次
obj
的函数上下文this
的援用值是他本人obj
闭包中应用 this 时,this 的援用值什么
在闭包中应用 this 会让代码变简单。如果外部函数没有应用 箭头函数 定义,则 this 对象会在运行时绑定到执行函数的上下文。如果在全局函数中调用,则 this 在非严格模式下等于 window,在严格模式下等于 undefined。如果作为某个对象的办法调用,则 this 等于这个对象。
从这一段话中咱们能够提取出以下几条信息。
- 如果闭包的外部函数是应用箭头函数定义的,根本不受影响,咱们只须要依照箭头函数的
this
指向判断办法判断就能够。 - 如果在全局函数中调用,则 this 在非严格模式下等于 window,在严格模式下等于 undefined
- 如果作为某个对象的办法调用,则 this 等于这个对象
外部函数应用箭头函数定义的,根本不受影响
window.identity = "The Window"
let object = {
identity: "My Object",
getIdentityFunc() {const doit = () => {console.log(this.identity)
}
return doit
},
}
object.getIdentityFunc()() // My Object
如果在全局函数中调用,则 this 在非严格模式下等于 window,在严格模式下等于 undefined
window.identity = "The Window"
let object = {
identity: "My Object",
getIdentityFunc() {return function () {console.log(this.identity)
}
},
}
object.getIdentityFunc()() // The Window
如果作为某个对象的办法调用,则 this 等于这个对象
window.identity = "The Window"
let object = {
identity: "My Object",
testIdentity: this.identity,
getIdentityFunc: () => {console.log(this.identity)
},
getIdentityFunc1() {return function () {console.log(this.identity)
}
},
getIdentityFunc2() {function doit() {console.log(this.identity)
}
return doit
},
getIdentityFunc3() {const doit = () => {console.log(this.identity)
}
return doit
},
}
object.getIdentityFunc() // The Window
object.getIdentityFunc1()() // The Window
object.getIdentityFunc2()() // The Window
object.getIdentityFunc3()() // My Object
let object1 = {
identity: "My Object1",
getIdentityFunc1: object.getIdentityFunc1(),
getIdentityFunc2: object.getIdentityFunc2(),}
object1.getIdentityFunc1() // My Object1
object1.getIdentityFunc2() // My Object1
练习题目
const test = {
name: "Bill",
show1: function () {console.log(this.name)
},
show2: () => {console.log(this.name)
},
show3: () => {function innerFunction() {console.log(this.name)
}
innerFunction()},
}
test.show1()
test.show2()
test.show3()
// 参考答案
Bill
undefined
undefined
var name = "window"
var person1 = {
name: "person1",
foo1: function () {console.log(this.name)
},
foo2: () => console.log(this.name),
foo3: function () {return function () {console.log(this.name)
}
},
foo4: function () {return () => {console.log(this.name)
}
},
}
var person2 = {name: "person2"}
person1.foo1()
person1.foo1.call(person2)
person1.foo2()
person1.foo2.call(person2)
person1.foo3()()
person1.foo3.call(person2)()
person1.foo3().call(person2)
person1.foo4()()
person1.foo4.call(person2)()
person1.foo4().call(person2)
// 参考答案
person1
person2
window
window
window
window
person2
person1
person2
person1
var name = "window"
function Person(name) {
this.name = name
this.foo1 = function () {console.log(this.name)
}
this.foo2 = () => console.log(this.name)
this.foo3 = function () {return function () {console.log(this.name)
}
}
this.foo4 = function () {return () => {console.log(this.name)
}
}
}
var person1 = new Person("person1")
var person2 = new Person("person2")
person1.foo1()
person1.foo1.call(person2)
person1.foo2()
person1.foo2.call(person2)
person1.foo3()()
person1.foo3.call(person2)()
person1.foo3().call(person2)
person1.foo4()()
person1.foo4.call(person2)()
person1.foo4().call(person2)
// 参考答案
person1
person2
person1
person1
window
window
person2
person1
person2
person1
window.identity = "The Window"
let object = {
identity: "My Object",
testThis: this.identity,
getIdentityFunc() {console.log(this.identity)
},
getIdentityFunc1: () => {console.log(this.identity)
},
getIdentityFunc2: () => {function innerFunction() {console.log(this.identity)
}
innerFunction()},
getIdentityFunc3() {return function () {console.log(this.identity)
}
},
getIdentityFunc4() {return () => {console.log(this.identity)
}
},
getIdentityFunc5: () => {return function () {console.log(this.identity)
}
},
getIdentityFunc6: () => {return () => {console.log(this.identity)
}
},
getIdentityFunc7() {console.log(this.identity)
function innerFunction() {console.log(this)
console.log(this.identity)
}
innerFunction()},
getIdentityFunc8() {const innerFunction = () => {console.log(this.identity)
}
innerFunction()},
}
object.getIdentityFunc() // My Object
let getIdentityFunc = object.getIdentityFunc
getIdentityFunc() // The Window
object.getIdentityFunc1() // The Window
let getIdentityFunc1 = object.getIdentityFunc1
getIdentityFunc1() // The Window
object.getIdentityFunc2() // The Window
let getIdentityFunc2 = object.getIdentityFunc2
getIdentityFunc2() // The Window
object.getIdentityFunc3()() // The Window
let getIdentityFunc3 = object.getIdentityFunc3()
getIdentityFunc3() // The Window
object.getIdentityFunc4()() // My Object
let getIdentityFunc4 = object.getIdentityFunc4()
getIdentityFunc4() // My Object
object.getIdentityFunc5()() // The Window
let getIdentityFunc5 = object.getIdentityFunc5()
getIdentityFunc5() // The Window
object.getIdentityFunc6()() // The Window
let getIdentityFunc6 = object.getIdentityFunc6()
getIdentityFunc6() // The Window
object.getIdentityFunc7()
object.getIdentityFunc8()
// 参考答案
My Object
The Window
The Window
The Window
The Window
The Window
The Window
The Window
My Object
My Object
The Window
The Window
The Window
The Window
The Window
My Object
文章参考文献
- 《JavaScript 高级程序设计》
- JavaScript 之彻底搞懂 this 的指向