本文主要討論一下JS的做用域和this
關鍵字。做用域,就是你的方法或者變量可訪問的區域,是他們執行的上下文。若是你見過這樣的代碼:javascript
function someFunc() { var _this = this; something.on("click", function() { console.log(_this); }); };
你就會很好奇爲何要用this
賦值給一個變量_this
呢?你看完這篇文章就會清楚這個問題的答案了。java
第一種做用域叫作全局做用域(Global Scope)這很容易定義,若是一個方法、變量是全局做用域的,那麼它就能夠從任何的地方訪問到。在瀏覽器裏,全局做用域就是window
對象。因此,若是你的代碼裏有:ajax
var x = 9;
你實際上是在給window.x
賦值爲9
(在瀏覽器裏運行的時候)。若是你喜歡的話,也能夠寫成window.x = 9
,固然這不是很必要。全局做用域對象的屬性能夠在代碼的任何地方訪問到。瀏覽器
另外的做用域就只有局部做用域了。在JavaScript裏通常就是一個方法內部的做用域。好比:this
function someFunction() { var x = 5; } console.log(x); // undefined
變量x
是在方法內部初始化的,那麼就只能在方法內部訪問。code
若是你聲明瞭一個變量,並且在聲明的時候忘記使用var
關鍵字。那麼,這個變量自動被置爲全局變量。好比:對象
function someFunction(){ x = 5; } // 執行一個這個方法,完成x的全局設置 someFunction(); console.log(x); // 5
這是一個很是差的實踐。你應該儘可能少的往全局做用域添加屬性。這也是爲何你會常常看到一些庫,好比jQuery會這麼幹:事件
(function() { var jQuery = {/*所有的方法都在這裏*/}; window.jQuery = jQuery; })();
把全有的屬性、方法都放在一個方法裏。而後馬上執行這個方法就會把所有的屬性和方法都綁定在了局部做用域裏。最後把jQuery
對象綁定到全局做用域,間接的把以前定義的屬性和方法都暴露出來方便調用。顯然我大量的減小了jQuery的代碼,可是這就是jQuery代碼如何工做的。ip
因爲局部做用域只有經過方法的定義來實現。任何在一個方法內部定義的方法均可以訪問外部方法裏定義的變量。好比:作用域
function outer() { var x = 5; function inner() { console.log(x); // 5 } inner(); }
可是outer()
方法不能夠訪問inner()
方法定義的任何變量。
function outer() { var x = 5; function inner() { console.log(x); // 5 var y = 100; } inner(); console.log(y); // undefined }
這很容易理解。可是當咱們試圖要探究this
關鍵字的時候就又變得複雜了。我相信不少人都遇到過這樣的問題:
${'myLink'}.on('click', function() { console.log(this); // 指向myLink $.ajax({ // 設置ajax相關 success: function() { console.log(this); // 指向的是全局對象。 ??? } }); });
this
是在方法執行的時候自動賦值的變量。它的值和方法的調用方式有很大的關係。好比:
function foo() { console.log(this); // global object } theApp = {}; theApp.foo = function() { console.log(this); // 指向theApp對象 } var link = doeument.getElementById('myLink'); link.addEventListener('click', function() { console.log(this); // 指向link });
MDN對第三個例子的解釋很是到位:
事件的this老是指向出發這個事件的元素對象。好比使用一個通用的事件監聽器來處理一系列的有類似事件的元素。當使用addEventListener把一個方法添加到一個元素的事件處理器的時候,這個方法的this值就被改變了。注意,this的值是從調用者裏傳給方法的。
這麼作:$('myLink').on('click', function() {})
意味着link被點擊的時候方法就會執行。因爲這個方法是處理link的事件的,因此this的值就是這個link元素。
在Ajax請求的success回調方法只是一個普通的方法。因此,當它被調用的時候this指向的是全局對象。任何對象,不是對象方法或者事件的時候會遇到的狀況。
上面的緣由也就是你在不少地方看到var _this = this;
或者var that = this;
的緣由。來看一個例子:
$('myLink').on('click', function() { console.log(this); //指向myLink var _this = this; $.ajax({ // ajax設置 success: function() { console.log(this); // 指向全局對象 console.log(_this); // 指向myLink } }); });