前言
本文将从以下几方面论述 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 Objectconst getIdentityFunc = object.getIdentityFuncgetIdentityFunc() // 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 Windowobject.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 Windowobject.getIdentityFunc() // The Windowobject.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 Objectobj.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 Windowobject.getIdentityFunc1()() // The Windowobject.getIdentityFunc2()() // The Window object.getIdentityFunc3()() // My Objectlet object1 = { identity: "My Object1", getIdentityFunc1: object.getIdentityFunc1(), getIdentityFunc2: object.getIdentityFunc2(),}object1.getIdentityFunc1() // My Object1object1.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()// 参考答案Billundefinedundefined
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)// 参考答案person1person2windowwindowwindowwindowperson2person1person2person1
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)// 参考答案person1person2person1person1windowwindowperson2person1person2person1
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 Objectlet getIdentityFunc = object.getIdentityFuncgetIdentityFunc() // The Windowobject.getIdentityFunc1() // The Windowlet getIdentityFunc1 = object.getIdentityFunc1getIdentityFunc1() // The Windowobject.getIdentityFunc2() // The Windowlet getIdentityFunc2 = object.getIdentityFunc2getIdentityFunc2() // The Windowobject.getIdentityFunc3()() // The Windowlet getIdentityFunc3 = object.getIdentityFunc3()getIdentityFunc3() // The Windowobject.getIdentityFunc4()() // My Objectlet getIdentityFunc4 = object.getIdentityFunc4()getIdentityFunc4() // My Objectobject.getIdentityFunc5()() // The Windowlet getIdentityFunc5 = object.getIdentityFunc5()getIdentityFunc5() // The Windowobject.getIdentityFunc6()() // The Windowlet getIdentityFunc6 = object.getIdentityFunc6()getIdentityFunc6() // The Windowobject.getIdentityFunc7()object.getIdentityFunc8()// 参考答案My ObjectThe WindowThe WindowThe WindowThe WindowThe WindowThe WindowThe WindowMy ObjectMy ObjectThe WindowThe WindowThe WindowThe WindowThe WindowMy Object
文章参考文献
- 《JavaScript 高级程序设计》
- JavaScript之彻底搞懂this的指向