JavaScript面向對象中的嚴格模式

概述

嚴格模式是什麼

嚴格模式是JavaScript中的一種限制性更強的變種方式。嚴格模式不是一個子集:它在語義上與正常代碼有着明顯的差別。
不支持嚴格模式的瀏覽器與支持嚴格模式的瀏覽器行爲上也不同,因此不要在未經嚴格模式特性測試狀況下使用嚴格模式。
嚴格模式能夠與非嚴格模式共存,因此腳本能夠逐漸的選擇加入嚴格模式。數組

嚴格模式的目的

首先嚴格模式會將JavaScript陷阱直接變成明顯的錯誤。
其次就是嚴格模式修正了一些引擎以優化的錯誤:一樣的代碼有時候嚴格模式會比非嚴格模式下更加流暢。
而後,嚴格模式禁用了一些有可能在將來版本中定義的語法。瀏覽器

開啓嚴格模式

全局開啓嚴格模式

若是想要在JavaScript中開啓嚴格模式,首先要在全部代碼的最前面,定義一個不會賦給任何變量的字符串。
若是以前的JavaScript代碼是非嚴格模式的話,建議不要盲目的爲這段代碼開啓嚴格模式,這樣可能會出現問題。在初學時期建議按一個個的函數去開啓嚴格模式。app

// 開啓嚴格模式 - 做用於全局做用域
// "use strict"
// 定義一個變量 - 不使用var關鍵字
a = 100;
//在非嚴格模式中能夠不使用var關鍵字,可是嚴格模式不能夠,否則就會報錯。
console.log(a);

function fn(){
    // 開啓嚴格模式 - 做用於函數做用域
    "use strict"
    v = 200;
    console.log(v);
}
fn();

函數開啓嚴格模式

嚴格模式也能夠爲一個指定的函數開啓。dom

function fn(){
    'use strict'
    //在函數體中開啓嚴格模式,可是函數意外依舊是非嚴格模式
    v = 200;
    consolo.log(v);
}
fn();

變量

禁止意外建立變量

在嚴格模式的狀況下,是不容許建立全局變量的。函數

// 開啓嚴格模式
"use strict";

v = 100;//不使用var關鍵字
console.log(v);

function fn(){
    // 在非嚴格模式:在函數做用域中定義變量 - 不使用var關鍵字 -> 自動將其提高爲全局變量
    w = 200;
    console.log(w);
}
fn();
console.log(w);

靜默失敗轉爲異常

所謂的靜默失敗就是即不報錯也沒有任何效果。例如改變常量的值。在嚴格模式下,靜默失敗會轉換成拋出異常。測試

// 開啓嚴格模式
"use strict";

const v = 3.14;// 定義常量
v = 1.14;// 從新賦值。嚴格模式下結果報錯。

console.log(v);

禁用delete關鍵字

在嚴格模式下,不能使用變量使用delete運算符,可是這種狀況只針對變量,對數組和對象屬性沒有限制。優化

// 開啓嚴格模式
"use strict";
// 嚴格模式下禁用delete關鍵字 -> 針對刪除變量,而不是數組元素和對象屬性

// var v = 100;// 定義一個全局變量
// console.log(v);
//
// delete v;// 刪除全局變量v
// console.log(v);// undefined
定義數組
// var arr = [1,2,3,4,5];
// delete arr[0];
// console.log(arr);
定義對象
var obj = {
    name : '張無忌'
}
delete obj.name;
console.log(obj.name);

對變量名的限制

在嚴格模式下,JavaScript對變量名也有限制。特別不能使用以下內容做爲變量:this

clipboard.png

上述內容都是保留字,在ECMAScript的下一個版本中可能會用到他們。
可是在嚴格模式下,使用上述標示符做爲變量名會致使語法錯誤。spa

// 開啓嚴格模式
"use strict";

var static = 100;
console.log(static);//結果-報錯

對象

不可刪除的屬性

在嚴格模式下,不能使用delete運算符刪除不可刪除的屬性。prototype

開啓嚴格模式
"use strict";
//在非嚴格模式下使用delete刪除不可刪除的屬性
 delete Object.prototype;//結果會靜默失敗
 console.log(Object.prototype);

//在嚴格模式下使用delete刪除不可刪除額屬性,結果就是拋出異常。
delete Math.random;
console.log(Math.random);
// Math.random();

屬性名必須惟一

在嚴格模式下,一個對象的全部屬性名在對象內必須惟一。

// 開啓嚴格模式
"use strict";

//在非嚴格模式下重名是容許的,最後一個重名的屬性就會覆蓋以上的屬性
//當開啓嚴格模式,重名屬性就會被認爲是語法錯誤
var obj = {
    name : '張三',
    name : '李四'
}
console.log(obj.name);

只讀屬性的賦值

在嚴格模式下,不能爲一個只讀的屬性進行從新賦值。

// 開啓嚴格模式
"use strict";

var obj = {
    name : '張無忌'
}
// 用於判斷指定屬性是否爲只讀屬性
var result = Object.getOwnPropertyDescriptor(obj, 'name');
console.log(result);//在非嚴格模式下爲只讀屬性從新賦值,結果會爲靜默失敗。
// 定義對象obj的只讀屬性
Object.defineProperty(obj, 'age', {
    value : 18
});
// 針對只讀屬性進行修改操做
// obj.age = 80;
// console.log(obj.age);

delete obj.age;
console.log(obj.age);

不可擴展的對象

在嚴格模式下,不能爲不可擴展的對象添加新屬性。

// 開啓嚴格模式
"use strict";

var obj = {};
// 設置對象obj是一個不可擴展的對象
Object.preventExtensions(obj);

// 爲對象obj新增屬性
obj.name = '張無忌';
console.log(obj);
//在非嚴格模式下爲不可擴展的對象添加新屬性,結果是靜默失敗。

函數

參數名必須惟一

在嚴格模式下,要求命名函數的參數必須惟一。

// 開啓嚴格模式
"use strict";

function fn(a, a, b){
    console.log(a + a + b);
//在非嚴格模式下最後一個參數名就會以前的重名參數,以前的參數仍然能夠銅鼓arguments[i]來訪問。
//在開啓嚴格模式下,重名參數就會被認爲是語法錯誤。    
}
fn(1,2,3);

arguments的不一樣

在嚴格模式下,arguments對象的行爲也有所不一樣。
1.在非嚴格模式下,修改命名參數的值也會反應到arguments對象中。
2.在嚴格模式下,命名參數與arguments對象是徹底獨立的。

// 開啓嚴格模式
"use strict";

function fn(value){
    var value = '張無忌';
    console.log(value);// 張無忌 -> 就近原則
    /*
        * 非嚴格模式下 - arguments對象獲取參數的值與形參有關的
          * 若是局部變量與形參名相同 - 根據就近原則進行獲取
        * 嚴格模式下 - arguments對象獲取參數的值與形參無關的
     */
    console.log(arguments[0]);// 張無忌
}
fn('周芷若');

arguments.callee()

在嚴格模式下,不能使用arguments對象的callee()方法。

// 開啓嚴格模式
"use strict";
//在非嚴格模式下,arguments對象callee()方法,表示調用函數自己
// 在嚴格模式下,arguments對象沒法調用callee()方法,結果拋出異常
function fn(){
    console.log(arguments.length);
    // return arguments.callee;
}
fn();

函數聲明的限制

在嚴格模式下,只能在全局域和函數域中聲明函數。

// 開啓嚴格模式
"use strict";

// 在全局做用域
function fn(){
    // 在函數做用域
    function n(){}
    //在非嚴格模式下,函數的定義在人格位置聲明函數都是能夠的。
}
// 在嚴格模式下,函數的定義只能在全局做用域與函數做用域(不能在塊級做用域定義函數),語法錯誤
for (var i=0; i<10; i++) {
    // ECMAScript 6新增 - 存在着塊級做用域
    var v = 100;
    function f(){
        console.log('this is function');
    }
}
console.log(v);
f();

eval()函數

增長eval()做用域

在嚴格模式下使用eval()函數建立的變量只能在eval()函數內部使用。

// 開啓嚴格模式
"use strict";
//在非嚴格模式下eval()函數建立的變量在其餘位置能夠使用。
// 在嚴格模式下,增長eval做用域 - eval()函數定義的變量只能在當前eval()函數內部使用
eval('var v = 100;');
// 在全局做用域中調用變量 - 報錯
console.log(v);// 100

arguments對象

禁止讀寫

在嚴格模式下,禁止使用eval()和arguments做爲標示符,也不容許讀寫它們的值。
1.使用var聲明
2.賦值另外一個值
3.嘗試修改包含的值
4.用做函數名
5.用做命名的函數的參數
6.在try...catch語句中用做例外明

// 開啓嚴格模式
"use strict";
//在嚴格模式下,如下全部嘗試都致使語法錯誤
eval = 17;
arguments++;
++eval;
var obj = { set p(arguments) { } };
var eval;
try { } catch (arguments) { }
function x(eval) { }
function arguments() { }
var y = function eval() { };
var f = new Function("arguments", "'use strict'; return 17;");

this關鍵字

抑制this

在非嚴格模式下使用函數的apply()或call()方法時,null或undefined值會被轉換爲全局對象。
在嚴格模式下,函數的this值始終是指定的值(不管什麼值)。

// 開啓嚴格模式
"use strict";

var v = 100;

function fn(){
    console.log(this.v);
}

var obj = {
    v : 200
}

fn.call(obj);// this指向全局對象
相關文章
相關標籤/搜索