Strict Mode和Extended Mode - Javascript語法基礎 - Javascript核心

原文: http://pij.robinqu.me/JavaScript_Core/JavaScript_Basics/Strict_Mode.htmlphp

源代碼: https://github.com/RobinQu/Programing-In-Javascript/blob/master/chapters/JavaScript_Core/JavaScript_Basics/Strict_Mode.mdhtml

  • 本文須要補充更多例子
  • 本文存在批註,但該網站的Markdown編輯器不支持,因此沒法正常展現,請到原文參考。

Strict Mode和Extended Mode

本文上一個版本盜用了別人的文章,經讀者指出後我就刪掉了。因爲起草的時間在去年,我也不太清楚當初是怎麼把別人的文章複製進來的。本文除了介紹所謂的Strict Mode以外,還會介紹其餘關聯內容。node

JavaScript並非一個完美的語言。事實上,第一個版本的Brendan Eich1花費十天的時間創造的,你不能對它指望太多。以後,JavaScript在瀏覽器大戰中,成爲各方角逐的主要戰場。各大廠商各顯神通,其反作用是各類奇奇怪怪的行爲和各式不一的API。在以後,W3C和其餘社區團體花費了大量的精力來經過標準化來「淨化」全部Web開發相關的技術標準。git

但尷尬的是,瀏覽器廠商並非那麼徹底的實現了W3C和ECMAScript的各類標準。最後,經驗豐富的Javascript程序員,經過約束自身對Javascript的使用方法,來達到讓Javascript更高的可擁度。可能大部分人都讀過《JavaScript語言精粹》2這本書,其講述的就是如何在JavaScript語言中,取其精華,而後去其糟粕。程序員

而JavaScript的嚴格模式,則是另外一種緊箍咒,它的約束力來自運行時自己,而不是用戶的主觀行爲。也就是說,有不少模棱兩可,或是錯誤卻被容許的操做,被完全禁止了。目前支持嚴格模式的支持範圍3從IE10起跳,其餘常青瀏覽器也都是支持的。github

如何開啓

開啓全局模式只需在全部語句以前放置"use strict"字符串常量。web

全局開啓嚴格模式:瀏覽器

"use strict"
var v = "Hello world";

但注意,這樣會致使整個腳本內的代碼都在嚴格模式中執行。假如以前有些代碼並無考慮嚴格模式,這可能讓你的整個應用程序忽然失效。app

咱們更爲推薦的是,在某個函數內開啓嚴格模式:ecmascript

function mySuperMethod() {
    "use strict";
    var v = "Hello world";
}

function mySuckingMethod {
    //not in strict mode
}

嚴格模式的具體行爲

你們有須要記住一堆語言特性了。可是,還好這些內容是把「歪」的掰「直」了。有少數代碼例子來自於MDC4

拋出ReferenceError

  1. 試圖隱式建立全局變量

    ```
    "use strict"
    hello = "world"//throw
    ```

拋出TypeError

  1. 試圖修改已經被定義爲不可寫的屬性

    ```
    "use strict";
    var o = {};
    Object.defineProperty(o, "hello", {value:"world", wrtiable:false});
    o.hello = "bad boy";//throw
    ```

    其餘相似的還有:

    • 給只讀屬性賦值
    • 給不可擴展的對象新建屬性
  2. 試圖刪除不可刪除的屬性

    ```
    "use strict";
    delete Object.prototype; //throw
    ```
  3. arguments.callee不能被返回、刪除、修改;

    ```
    "use strict";
    var fun = function() { 
        return arugments.callee;//throw
    };
    ```

拋出SyntaxError

  1. 重複定義屬性名

    ```
    "use strict";
    var o = {hello: 1, hello: 2};//throw
    ```
  2. 禁用八進制字面量

    ```
    "use strict";
    var hello = 015;//throw
    ```
  3. 不容許重複參數名

    ```
    function myMethod(a, b, b) {//throw
        "use strict";
    }
    ```
  4. 不能使用with

    ```
    "use strict";
    var obj = {};
    with (obj) {};//throw
    ```
  5. 不容許對evalarguments賦值

    ```
    var fun = function(){
        "use strict";
        eval=16
    }();
    ```
  6. 不可將evalarguments做爲參數名、變量名

    ```
    var fun = function(){
        "use strict"; 
        var obj = { 
            set p(arguments) {} 
        };
    }();
    ```

eval被限制在臨時的本地做用域

eval再也不有權限直接修改其所在做用於,而只能影響自身建立的做用域。

var hello = "world";
var evalHello = eval("'use strict'; var hello = "girl"; hello");
// hello === "world"
// evalHello === "girl"

arguments再也不追蹤實際參數值變化

function f(hello)
{
  "use strict";
  hello = "girl";
  return [hello, arguments[0]];
}
var pair = f("world");
// pair[0] === "girl"
// pair[1] === "world";

函數的動態綁定後的this不作任何修改

  • 即便指定nullundefined,引擎也不會從新指定全局對象做爲this
  • 指定基礎數據類型時,也不會用包裝類進行轉換
"use strict";
function fun() { return this; }
// fun() === undefined
// fun.call(2) === 2
// fun.apply(null) === null
// fun.call(undefined) === undefined
// fun.bind(true)() === true

調用堆棧不可被追蹤

以往,咱們能夠經過函數的callerarguments來投影整個調用堆棧。可是,在嚴格模式中咱們作不到。

function restricted()
{
  "use strict";
  restricted.caller;    // throws a TypeError
  restricted.arguments; // throws a TypeError
}

ECMAScript6的相關特性

更多保留字

implements, interface, let, package, private, protected, public, static, yield

僅容許在開頭使用function語句

不少開發者喜歡以下代碼風格,這在嚴格模式中會報錯。

function foo()
{
  "use strict";
  return g;
  function g() { }//throw SyntaxError
}

這個改變的緣由是,JavaScript的Hoisting特性會讓不少人迷惑:

function g() { }
function foo()
{
    if (true)
    function g() { }
    return g;
}

Extended Mode

ES6 Draft中引入了一個新的概念5,叫Extend Mode,而後又被撤銷了6。但不幸的是,V8中已經支持了這個新模式。因此,做爲事實標準,目前依賴V8的全部Javascript運行環境都有以下三個模式:

  • Classic Mode,或者Non-strict mode
  • Strict Mode
  • Extended Mode

這個模式是備受爭議的。這個模式的產生,也體會出製做一個標準的困難之處——你總要考慮新標準對老標準的兼容,尤爲是Web技術。

有稍微瞭解ES6的同窗都應該清楚,moduleclass這些東西已經徹底顛覆了傳統JavaScript的不少嘗試。但也有很多東西,開發者是能夠接受,並立馬去嘗試的。因而乎,關於如何讓代碼部分進入extended mode也就成了最初討論的重點7

實際表現上,node的0.11.x的版本,有些特性,僅僅使用--harmony並不能徹底使用,還需加上--use_strict。在這裏,已經能夠看出V8團隊有多糾結了8。他們也沒有想清楚,該如何進入extended mode,索性,也叫strict吧。

目前僅在extended mode下可用的ES6特性:

  • let
  • blockl-level function declaration

關於ES6的特性,請參考本書的相關章節。

相關文章
相關標籤/搜索