在一個JavaScript文件中,我看到了: javascript
function Somefunction(){ var that = this; ... }
什麼是聲明的目的that
和分配this
本呢? css
這是使內部功能(在其餘功能內定義的功能)更按需工做的一種技巧。 在JavaScript中,當你定義裏面另一個功能, this
將自動被設置爲全局範圍。 這可能會形成混淆,由於您但願this
具備與外部函數相同的值。 html
var car = {}; car.starter = {}; car.start = function(){ var that = this; // you can access car.starter inside this method with 'this' this.starter.active = false; var activateStarter = function(){ // 'this' now points to the global scope // 'this.starter' is undefined, so we use 'that' instead. that.starter.active = true; // you could also use car.starter, but using 'that' gives // us more consistency and flexibility }; activateStarter(); };
當您將函數建立爲對象的方法(例如car.start
中的car.start
),而後在該方法內部建立函數(例如activateStarter
)時,這尤爲是一個問題。 在頂層方法中, this
指向對象,它是的方法(在本例中爲car
),可是在內部函數中, this
如今指向全局範圍。 真痛苦 java
建立一個變量以按慣例在兩個範圍內使用都是解決javascript這個很是廣泛的問題的方法(儘管它在jquery函數中也頗有用)。 這就是爲何很通常名曰that
被使用。 這是克服語言缺陷的一種容易識別的約定。 jquery
就像El Ronnoco在道格拉斯 ·克羅克福德( Douglas Crockford)暗示的那樣,這是一個好主意。 app
有時, this
能夠參考另外一個範圍,是指別的東西,例如,假設你要調用一個DOM事件中構造函數方法,在這種狀況下, this
將涉及到的DOM元素而不是建立的對象。 ide
的HTML 函數
<button id="button">Alert Name</button>
JS flex
var Person = function(name) { this.name = name; var that = this; this.sayHi = function() { alert(that.name); }; }; var ahmad = new Person('Ahmad'); var element = document.getElementById('button'); element.addEventListener('click', ahmad.sayHi); // => Ahmad
演示版 this
assing以上將解決this
要that
,而後咱們就能夠和訪問裏面的name屬性sayHi
來自法that
,因此這能夠被稱爲無DOM調用中的問題。
另外一個解決方案是分配一個空that
對象並添加屬性和方法,而後返回它。 可是使用此解決方案,您失去了構造函數的prototype
。
var Person = function(name) { var that = {}; that.name = name; that.sayHi = function() { alert(that.name); }; return that; };
若是您經過使用call()
或apply()
進行變通that
則實際上不須要使用它:
var car = {}; car.starter = {}; car.start = function(){ this.starter.active = false; var activateStarter = function(){ // 'this' now points to our main object this.starter.active = true; }; activateStarter.apply(this); };
這是一個例子
$(document).ready(function() { var lastItem = null; $(".our-work-group > p > a").click(function(e) { e.preventDefault(); var item = $(this).html(); //Here value of "this" is ".our-work-group > p > a" if (item == lastItem) { lastItem = null; $('.our-work-single-page').show(); } else { lastItem = item; $('.our-work-single-page').each(function() { var imgAlt = $(this).find('img').attr('alt'); //Here value of "this" is '.our-work-single-page'. if (imgAlt != item) { $(this).hide(); } else { $(this).show(); } }); } }); });`
所以,您能夠看到此值是兩個不一樣的值,具體取決於您定位的DOM元素,可是當您在上面的代碼中添加「 that」時,您將更改定位的「 this」的值。
`$(document).ready(function() { var lastItem = null; $(".our-work-group > p > a").click(function(e) { e.preventDefault(); var item = $(this).html(); //Here value of "this" is ".our-work-group > p > a" if (item == lastItem) { lastItem = null; var that = this; $('.our-work-single-page').show(); } else { lastItem = item; $('.our-work-single-page').each(function() { ***$(that).css("background-color", "#ffe700");*** //Here value of "that" is ".our-work-group > p > a".... var imgAlt = $(this).find('img').attr('alt'); if (imgAlt != item) { $(this).hide(); } else { $(this).show(); } }); } }); });`
..... $(that).css(「 background-color」,「#ffe700」); //這裏「 that」的值是「 .our-work-group> p> a」,由於var that = this; 所以,即便咱們位於「 this」 ='.our-work-single-page',咱們仍然可使用「 that」來操縱先前的DOM元素。
從克羅福德
按照慣例,咱們作一個私有變量 。 這用於使對象可用於私有方法。 這是爲在ECMAScript的語言規範的錯誤這將致使此不正確地對內部函數來設置一種解決方法。
function usesThis(name) { this.myName = name; function returnMe() { return this; //scope is lost because of the inner function } return { returnMe : returnMe } } function usesThat(name) { var that = this; this.myName = name; function returnMe() { return that; //scope is baked in with 'that' to the "class" } return { returnMe : returnMe } } var usesthat = new usesThat('Dave'); var usesthis = new usesThis('John'); alert("UsesThat thinks it's called " + usesthat.returnMe().myName + '\r\n' + "UsesThis thinks it's called " + usesthis.returnMe().myName);
這會提醒...
認爲那叫戴夫(Dave)
用途這被認爲是未定義的