JavaScript this的原理以及指向詳解
怎麼判斷this指向?
- ①在全域性環境中呼叫就指向window。
- ②作為物件的方法呼叫就指向該物件。
- ③作為建構函式呼叫就指向這個新建立的物件。
- ④可以使用apply,call,bind改變this指向。
- ⑤箭頭函式中的this與定義時所處的上下文繫結,且不能被改變, 箭頭函式this指向取決於它外層找到的離它最近的第一個非箭頭函式的this。
怎麼理解this原理?
語言學懂需要理解下面兩種寫法
var obj = { foo: function () {} }; var foo = obj.foo; // 寫法一 obj.foo() // 寫法二 foo()
這兩種寫法上一種是函式呼叫,一種是物件的方法,雖然obj.foo和foo都指向了一個函式,但是他們執行的結果卻可能不一樣,看看下面的程式碼:
var obj = { foo: function () { console.log(this.bar) },bar: 1 }; var foo = obj.foo; var bar = 2; obj.foo() // 1 foo() // 2
為什麼執行結果不一樣?因為函式關鍵體使用了this關鍵字,很多教材、資料會告訴你,this指的是函式執行時所在的環境。對於obj.foo()來說,foo執行在obj環境,所以this指向obj;對於foo()來說,foo執行在全域性環境,所以this指向全域性環境。所以,兩者的執行結果不一樣。
那麼到底是怎麼判斷this指向哪裡?或者說this執行在哪個環境裡?
var obj = { foo: 5 };
上邊一段程式碼將一個物件賦值給了變數obj,那麼Script的引擎會先在記憶體裡邊生成物件{foo : 5},然後將這個物件的地址賦值給obj。
obj 也就是一個變數地址,讀取obj.foo會先從obj中拿到記憶體地址,再從這個地址中讀取原始的物件,返回foo屬性。
foo屬性是如何儲存在記憶體中的?
{ foo: { [[value]]: 5 [[writable]]: true [[enumerable]]: true [[configurable]]: true } }
foo屬性的值儲存在屬性描述物件的value屬性裡面
如果屬性的值是一個函式呢?
var obj = { foo: function () {} };
這個時候,JavaScript引擎會將函式單獨儲存在記憶體中,然後再將函式的地址賦值給foo屬性的value屬性。
{ foo: { [[value]]: 函式的地址 ... } }
正因為函式是單獨儲存在記憶體中的,所以它可以在不同的環境(上下文)中執行。
var f = function () {}; var obj = { f: f }; // 單獨執行 f() // obj 環境執行 obj.f()
JavaScript允許在函式體內部,引用當前環境的其他變數。
var f = function () { console.log(x); };
這個函式裡邊就用到了其他變數X。
看下邊的程式碼
var f = function () { console.log(this.x); } var x = 1; var obj = { f: f,x: 2,}; // 單獨執行 f() // 1 // obj 環境執行 obj.f() // 2
可以看到函式執行的結果不一樣,函式f在全域性執行,那麼它的this呢?this.x指向全域性環境的x。
在obj環境中執行的obj.f呢,它的this顯然是在obj環境中,所以this指向obj環境下的obj.x。
所以,文章開頭,obj.foo()是通過obj找到foo,所以就是在obj環境中執行。一旦var foo = obj.foo,變數foo就直接指向函式本身,函式本身foo()是在全域性環境中,所以foo()就變成在全域性環境執行。
function foo() { console.log(this.name); } function FozoGdEzo(fn) { fn(); } var obj = { name: 'zl',foo,} var name = "Heternally"; Foo(obj.foo);
那麼上邊程式碼執行的結果是什麼呢?
到此這篇關於JavaScript this的原理以及指向詳解的文章就介紹到這了,更多相關JavaScript thiswww.cppcns.com內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!