如果你不知道这个系列为什么叫这种激烈的名字可以看这篇:
Day [0] — JS之浸猪笼系列
如果你还没看过这篇 ,可能会有点难理解今天这篇,建议你先企看看!
Day [1] — this:存在于物件 — JS之浸猪笼系列
Day [2] — this:作用域
直接进入範例主题!!!σ ゚∀ ゚) ゚∀゚)σ
//来个範例吧!var a = 100;var obj = { a: 200, fn: function() { var test = function() { console.log(this.a) } test() }}obj.fn() //100//....恩?为什么是100?(゚д゚≡゚д゚)//作用域去哪里ㄌ?他本来还在的啊?
先不要激动,我们来看看到底发生了什么事情....
//来个範例吧!//範例一解析var a = 100; //我们宣告 a = 100,这是一个全域变数var obj = {a: 200, // a 在物件内的值为 200fn: function() { var test = function() { console.log(this.a)}** test() } //记住我们在这里呼叫了test}obj.fn() //100//解析一下//让我们用倒叙法回推,//obj.fn() 所以我们要去找 obj(物件)里的 fn 的值,//往上看 fn,会发现 fn 是个函式,//他会运算出 var test = function() {console.log(this.a)} 的值,//记得我们在 fn 这个函式中 呼叫了 test();//让 this 去找出了第一行的 var a = 100; //什么意思?//意思是 this 自动去指向了 window !(没想到吧)//所以最后印出的值就是 obj.fn() //100
窝噗懂....为什么会这样?
让我们印得比说得快!σ ゚∀ ゚) ゚∀゚)σ
//来个範例吧!//範例二function hello(){ console.log(this)}hello()//猜猜这里会印出啥?//是......window !σ ゚∀ ゚) ゚∀゚)σ
从这边开始我们就可以正式进入This的正题了!为啥在上面那个範例里,this会指向window呢?
day[1]的文章 中提到『 this 在函数运行的时候自动指向 instance(物件实体) 的属性。』
在上面那个範例中,我们并没有让 this 指向任何的物件,那 this 会指向哪呢?
你以为答案永远是 window 吗? 错!σ ゚∀ ゚) ゚∀゚)σ
实际上在this没有被指向 instance(物件实体)时,会指向的地方有这三种:
严格模式底下就都是undefined
非严格模式,浏览器底下是window
非严格模式,node.js 底下是global
一但脱离了物件,this 的值就没什么意义,在没意义的情况底下就会有个预设值,而预设值也很好记,严格模式就是undefined,非严格模式底下就是全域物件。
(看懂这边的话可以在往上看一次範例一)
看了上面的解析和範例,聪明的你应该已经发现 this 的值跟作用域跟程式码的位置在哪里完全无关,只跟「你如何呼叫」有关。
//来个範例吧!//範例三const obj = { value: 1, hello: function() { console.log(this.value) }}obj.hello() // 这里会印出 1,我们怎么呼叫的?//我们最终的结果是要得到 obj.hello()//obj我们已经知道他是物件,//而其中 hello 是 function() {console.log(this.value)}//在 obj这个物件中,this 会自动指向到 obj,//当我们呼叫 obj.hello() 时等同于我们说 this 是 obj,//为啥?因为他就是个代名词!const hey = obj.hellohey() // 这里会印出 undefined,我们怎么呼叫的?//为什么换成 hey = obj.hello 就不是 1 了呢?//答案也是:因为作用域。//const hey = obj.hello 时,//hey已经形成一个封闭的作用域(注一),//所以 this 在 const(严格模式)底下就都是undefined。//注一://const → 区块作用域(block scope),其作用範围是在它们被定义的区块里面。
引用及参考资讯
What's THIS in JavaScript ? [上]
浅谈 JavaScript 头号难题 this:绝对不完整,但保证好懂
this 的值到底是什么?一次说清楚