本文主要討論一下JS的作用域和this
關(guān)鍵字春贸。作用域求类,就是你的方法或者變量可訪問的區(qū)域狱杰,是他們執(zhí)行的上下文。如果你見過這樣的代碼:
function someFunc() {
var _this = this;
something.on("click", function() {
console.log(_this);
});
};
你就會很好奇為什么要用this
賦值給一個變量_this
呢期奔?你看完這篇文章就會清楚這個問題的答案了侧馅。
第一種作用域叫做全局作用域(Global Scope)這很容易定義,如果一個方法呐萌、變量是全局作用域的馁痴,那么它就可以從任何的地方訪問到。在瀏覽器里肺孤,全局作用域就是window
對象罗晕。所以,如果你的代碼里有:
var x = 9;
你其實(shí)是在給window.x
賦值為9
(在瀏覽器里運(yùn)行的時候)渠旁。如果你喜歡的話攀例,也可以寫成window.x = 9
,當(dāng)然這不是很必要顾腊。全局作用域?qū)ο蟮膶傩钥梢栽诖a的任何地方訪問到粤铭。
另外的作用域就只有局部作用域了。在JavaScript里一般就是一個方法內(nèi)部的作用域杂靶。比如:
function someFunction() {
var x = 5;
}
console.log(x); // undefined
變量x
是在方法內(nèi)部初始化的梆惯,那么就只能在方法內(nèi)部訪問。
一些需要注意的地方
如果你聲明了一個變量吗垮,而且在聲明的時候忘記使用var
關(guān)鍵字垛吗。那么,這個變量自動被置為全局變量烁登。比如:
function someFunction(){
x = 5;
}
// 執(zhí)行一個這個方法怯屉,完成x的全局設(shè)置
someFunction();
console.log(x); // 5
這是一個非常差的實(shí)踐。你應(yīng)該盡量少的往全局作用域添加屬性。這也是為什么你會經(jīng)诚锹纾看到一些庫赌躺,比如jQuery會這么干:
(function() {
var jQuery = {/*全部的方法都在這里*/};
window.jQuery = jQuery;
})();
把全有的屬性、方法都放在一個方法里羡儿。然后立刻執(zhí)行這個方法就會把全部的屬性和方法都綁定在了局部作用域里礼患。最后把jQuery
對象綁定到全局作用域,間接的把之前定義的屬性和方法都暴露出來方便調(diào)用掠归。顯然我大量的減少了jQuery的代碼缅叠,但是這就是jQuery代碼如何工作的。
由于局部作用域只有通過方法的定義來實(shí)現(xiàn)虏冻。任何在一個方法內(nèi)部定義的方法都可以訪問外部方法里定義的變量肤粱。比如:
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
}
這很容易理解兄旬。但是當(dāng)我們試圖要探究this
關(guān)鍵字的時候就又變得復(fù)雜了狼犯。我相信很多人都遇到過這樣的問題:
${'myLink'}.on('click', function() {
console.log(this); // 指向myLink
$.ajax({
// 設(shè)置ajax相關(guān)
success: function() {
console.log(this); // 指向的是全局對象。 领铐?悯森??
}
});
});
this
是在方法執(zhí)行的時候自動賦值的變量绪撵。它的值和方法的調(diào)用方式有很大的關(guān)系瓢姻。比如:
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總是指向出發(fā)這個事件的元素對象。比如使用一個通用的事件監(jiān)聽器來處理一系列的有相似事件的元素音诈。當(dāng)使用addEventListener把一個方法添加到一個元素的事件處理器的時候幻碱,這個方法的this值就被改變了。注意细溅,this的值是從調(diào)用者里傳給方法的褥傍。
這么做:$('myLink').on('click', function() {})
意味著link被點(diǎn)擊的時候方法就會執(zhí)行。由于這個方法是處理link的事件的喇聊,所以this的值就是這個link元素恍风。
在Ajax請求的success回調(diào)方法只是一個普通的方法。所以誓篱,當(dāng)它被調(diào)用的時候this指向的是全局對象朋贬。任何對象,不是對象方法或者事件的時候會遇到的情況窜骄。
上面的原因也就是你在很多地方看到var _this = this;
或者var that = this;
的原因锦募。來看一個例子:
$('myLink').on('click', function() {
console.log(this); //指向myLink
var _this = this;
$.ajax({
// ajax設(shè)置
success: function() {
console.log(this); // 指向全局對象
console.log(_this); // 指向myLink
}
});
});
原文地址:https://javascriptplayground.com/javascript-variable-scope-this/