2012-09-03 26 views
2

更新不一致的行爲「這個」在JavaScript嚴格模式

爲清楚:@FelixKing:是的,我希望this仍然調用window.foo()時是不確定的,和這裏的原因:因爲,在JavaScript:

function foo() 
{ 
    console.log('I am a function'); 
} 

是(幾乎)同樣的事情:

var foo = function() 
{ 
    console.log('I am a function'); 
} 

foo === window.foo評估爲真,我希望他們都行爲相似。如果函數是變量,並且JS回退到全局對象(在函數x中,變量沒有被聲明,但是你使用它,JS 氣泡遍歷所有範圍,直到全局對象,直到它找到變量問題,還是在全球範圍內創建它),如果事先指定window對象,則無關緊要。然而,當你這樣做時,行爲會發生變化,這是我沒有想到的。
我有一個直覺至於爲什麼這是這種情況(我定義的方法,而不是變量),但是再次,對於全局對象,它們之間幾乎沒有什麼區別。 var c = 'Variable'; console.log(window.c === c);記錄真實等...但我想知道什麼實際上是什麼,以及它是如何工作的(在所有級別上)。

我準備儘可能接受foo.apply(this,[]);foo.apply(window,[]);可以強制this指向全局對象去,但不是window.foo();。如果嚴格保護全球對象,我會說這是讓後門敞開。例如,我偶爾會發現自己調用函數,具體取決於變量的值。爲此,我使用window[myVar]();,嚴格與否,這意味着this指向全局對象,而如果我直接調用該函數則不會。就我而言,這是不一致的。


我遇到的嚴格模式this關鍵字一些怪異的行爲。不要誤解我的意思thisundefined in strict functions。我發現令人困惑的是,this可能被迫指向全局對象(或任何其他對象,就此而言),從而有效地破壞嚴格模式提供的安全網。這也有其他影響。考慮以下代碼:

'use strict';//using strict everywhere 
(function(Global) 
{ 
    var closureObject = {}; 
    Global.foo = function() 
    { 
     closureObject.setIn = closureObject.setIn || 'Set in foo'; 
     console.log(this); 
     console.log(this === Global); 
     bar(); 
     bar.apply(this); 
     return (this !== Global ? this : undefined); 
    }; 
    Global.bar = function() 
    { 
     closureObject.setIn = closureObject.setIn || 'set in bar'; 
     console.log(this); 
     return (this !== Global ? this : undefined); 
    }; 
})(this); 
var undef = (Math.ceil(Math.random()*10)%2 ? foo() : bar()); 
foo();//undefined --- false​​​​​​​​​​​​​​​​​ --- undefined --- undefined 
window.foo();//Window --- true --- undefined --- window 
foo.apply(this,[]);//same as window.foo 

同樣適用於自定義對象:

function Foo(n) 
{ 
    this.name = n; 
} 
Foo.prototype.func = foo;//or window.foo 
//other objects: 
var d = new Date(); 
foo.apply(d,[]);//Date --- false --- undefined --- date 

這,在我看來,是黑客和陷阱的可能來源。更重要的是:它使相當難以確定調用是來自:如果foo()從全局對象(window.foo();)呼籲,這方面當然不會傳遞到bar的,除非bar將使用稱爲bar.apply(this,[]);

爲什麼我想要一個乾淨,安全和可靠的方法來確定調用者上下文很簡單:我使用閉包來避免那些討厭的全局變量,但同時我設置了一些作爲事件處理程序的函數。
我知道沒有使用嚴格模式,或者設置全局很容易修復,但嚴格模式是留在這裏,我喜歡它帶給派對的東西(好吧,大部分)。我堅信這就是JS發展的方式,我不願意爲自己破碎的代碼哭泣,因爲他不想打擾strict。這可能不會發生得太快,但我只是想讓我的知識保持最新。

我已閱讀strict上的MDN頁面,以及John Resig的博客文章,我觀看了很多DC的視頻並閱讀了他的許多文章,但我還沒有找到關於該文章的明確說明我上面描述的行爲。我還沒有讀完整個ECMAScript標準(男孩,那些東西太乾燥了,它可能會耗盡撒哈拉沙漠),但也許這裏有人可能會指出我正確的方向來幫助我更好地理解這一點。

+3

這裏的不一致行爲究竟是什麼?如果你調用'window.foo()',你是否期望'this'也是'undefined'? –

+0

從我這個問題來看,''this''可以很好地被引用,當不在函數中時(在JS中沒有'main()')。正如我所看到的,這正是發生在這裏的事情。 – raina77ow

+0

從我讀過的'這個'沒有指出在嚴格模式下未定義,以避免當它們不應該被設置的全局變量(例如;沒有'new'關鍵字的構造函數)。我期望'window.foo()'不會改變這一點,如果整個問題不是設置全局變量,那麼全局上下文應該被禁止,不是嗎?我的意思是,一致性是什麼嚴格的模式是對的,對嗎?爲什麼然後啓用哈克解決方法? –

回答

2

我不知道如果我在讀你的問題的權利,但它好像您有一個事實,即func.apply(context, arguments)可以採取context因爲這將在隨後被this在函數內部下文稱參數的麻煩。

我認爲經過背景下是必要的和JavaScript不能沒有它正常工作。

關閉我的頭頂,因爲沒有super正確使用繼承的唯一方法是使用像BaseClass.prototype.baseFunction.apply(this, arguments)之類的東西。

刪除該功能將創造一個語言今天是從JavaScript非常不同的,是不是有什麼strict模式是什麼。

+0

對不起,我想我的問題可能是更清楚這不是。 'apply',或'call',甚至不是問題的上下文設置,只是'window.foo()'打開全局對象,而'foo()'不是,甚至儘管'foo()'意味着最接近的'foo'定義,在這種情況下:全局的。允許'window.foo();'將'this'設置爲全局的風險很大,很多人使用'window [someVar] ()'調用函數打開了全球的對象,是有風險的。應該是可能的,但只'call'和'apply' BC,顯示清晰的意圖,是不是 –

+1

@Elias:。?你可以儘管對'ab()'使用了相同的參數,我使用'foo.bar()',因爲我想'this'指向'bar'裏面的'foo',它也顯示了我的明確意圖。看到'窗口。 foo()'作爲異常,因爲'window'是一個對象以及全局對象。無論如何,我不認爲這是討論這個問題的合適地點,也許它更適合一些ECMA郵件列表。或者期望從答案中得到什麼?爲什麼它是這樣的解釋? (因爲分配給屬性的調用函數像這樣工作);爲什麼'window'不包括在內?還是同意? –

+0

@Elias如果在'window.foo()'*的上下文中'this'不會指向'window',我會稱它不一致。 –

相關問題