JS '嚴格模式'

weixin_33890499發表於2015-12-03

為什麼想到寫這麼一篇文章呢,來源在於回答一個 SG上面的問題。那麼問題是這樣子的。

var a = 2; 
function foo(){ console.log(this.a);}
foo();

以上程式碼,執行的結果是什麼??

如果你回答是2,那麼對了多少?

只能說對了一半,為什麼呢? 其實是題主的問法有問題,他沒有規定環境,所以答案很多,
直接在瀏覽器裡面如下寫法執行

 <script>
    var a = 2; 
    function foo(){ console.log(this.a);}
    foo();
 </script>

確實會輸出2,沒有問題。

但是如果在 nodejs裡面, 大家考慮過麼?

結果是可能是2,可能是 undefined。 現在有人是不是蒙圈了,不知道為什麼。那麼解析的文章在

http://f2e.souche.com/blog/a-js-problem-about-global/

甚至還有後續,可以看 sg上的原問題,

http://segmentfault.com/q/1010000004053433?_ea=473968

在評論中討論到了一個問題,如果在瀏覽器中使用 ‘嚴格模式’, 會怎麼樣?

 <script>
    "use strict"
    var a = 2; 
    function foo(){ console.log(this.a);}
    foo();
 </script>

結果就是會報錯,錯誤如下,是不是出乎大家的意料,

  Uncaught TypeError: Cannot read property 'a' of undefined(…)
198062-2ebc5e6d2b03973d.png
Paste_Image.png

那麼為什麼呢? 我們列印下 this 關鍵字看看, 發現是 undefined。 我操,這跟我們的想法不符合啊,為何不是window這個全域性變數了?? 這一切的原因在於 "use strict"

那麼什麼是嚴格模式,mozile的官方文件解釋在這裡
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode#Securing_JavaScript

主要注意點在 “Changes in strict mode” 這個欄目下,“ Securing JavaScript” 第一條

First, the value passed as this to a function in strict mode is not forced into being an object (a.k.a. "boxed"). For a normal function, this is always an object: either the provided object if called with an object-valued this; the value, boxed, if called with a Boolean, string, or number this; or the global object if called with an undefined or null this. (Use call, apply
, or bind
to specify a particularthis
.) Not only is automatic boxing a performance cost, but exposing the global object in browsers is a security hazard, because the global object provides access to functionality that "secure" JavaScript environments must restrict. Thus for a strict mode function, the specified this is not boxed into an object, and if unspecified, this will be undefined:

  "use strict";function fun() { return this; }
  console.assert(fun() === undefined);
  console.assert(fun.call(2) === 2);
  console.assert(fun.apply(null) === null);
  console.assert(fun.call(undefined) === undefined);
  console.assert(fun.bind(true)() === true);

意思就是不會在預設的給function指定一個this物件了。 一般情況下,我們的function一定會有一個呼叫物件,不管是字元還是陣列什麼的,或者是全域性變數,這種轉換很損耗效能,而且危險,因為暴露了全域性物件,所以嚴格模式下,不會再封裝this物件了,如果沒有,就是 undefined。

以上就是我們執行出來,報錯的原因。至於這個模式到底好不好呢? 其實有些爭議的,很多人寫js已經習慣了這些各種變化,或者說是為方便吧,但是很多剛開始寫的人很不習慣,甚至搞不明白,仁者見仁智者見智吧。

一篇簡單的探索,這個嚴格模式 出來很早了,很多人都有寫過,而且官方文件很詳細。當然更關鍵的是你不使用也沒有任何問題,一旦使用就要注意了哦。

相關文章