这篇翻译不完整。请帮忙从英语翻译这篇文章。
不推薦使用with語句,因為可能造成bug或者性能損失。詳見
"Description"的"Ambiguity Con"部分。概要
with語句的作用是擴展作用域鏈(scope chain)。
語法
with (expression) { statement }
expression
- 將expression添加到作用域鏈,以便在statement中計算值的時候使用。expression 外面需加括號。
statement
- 任何語句都行。如果不止一句,則需用block符號({ ... })將其括起來。
說明
JavaScript查找某個未使用命名空間的變量時,會通過作用域鏈來查找,作用域鏈是跟執行代碼的context或者包含這個變量的函數有關。'with'語句將某個對象添加的作用域鏈的頂部,如果在statement中有某個未使用命名空間的變量,跟作用域鏈中的某個屬性同名,則這個變量將指向這個屬性值。如果沒有同名的屬性,則將拋出ReferenceError
異常。
with
is not recommended, and is forbidden in ECMAScript 5 strict mode. The recommended alternative is to assign the object whose properties you want to access to a temporary variable.性能方面的利與弊
利:with語句可以在不造成性能損失的情況下,減少變量的長度。其造成的附加計算量很少。使用
'with'可以減少不必要的指針路徑解析運算。需要注意的是,很多情況下,也可以不使用with語句,而是使用一個臨時變量來保存指針,來達到同樣的效果。
弊:with語句使得程序在查找變量值時,都是先在指定的對象中查找。所以那些本來不是這個對象的屬性的變量,查找起來將會很慢。如果是在對性能要求較高的場合,
'with'下面的statement語句中的變量,只應該包含這個指定對象的屬性。
語義不明的弊端
弊端:with語句使得代碼不易閱讀,同時使得
JavaScript編譯器不易在作用域鏈上查找某個變量,不易決定應該在哪個對象上來取值。請看下面的例子:
function f(x, o) { with (o) print(x); }
f被調用時,
x有可能能取到值,也可能是undefined
,如果能取到, 有可能是在o上取的值,也可能是函數的第一個參數x的值(如果o中沒有這個屬性的話)。如果你忘記在作為第二個參數的對象o中定義x這個屬性
,程序並不會報錯,只是取到另一個值而已。
弊端:使用
with語句的代碼,無法向前兼容,特別是在使用一些原生數據類型的時候。看下面的例子:
function f(foo, values) { with (foo) { console.log(values) } }
如果是在
ECMAScript 5環境調用f([1,2,3], obj),則with語句中變量
values將指向函數的第二個參數values。但是,
ECMAScript 6標準給Array.prototype添加了一個新屬性values,所有數組實例將繼承這個屬性。所以在
ECMAScript 6環境中,with語句中變量
values將指向
[1,2,3].values
。
示例
Example: Using with
下面的with語句指定
Math對象作為默認對象
。with語句裡面的變量,分別指向Math對象的
PI
、cos和
sin函數,不用在前面添加命名空間(Math.PI)
。
var a, x, y; var r = 10; with (Math) { a = PI * r * r; x = r * cos(PI); y = r * sin(PI / 2); }
技術規範
Specification | Status | Comment |
---|---|---|
ECMAScript 1st Edition. | Standard | Initial definition. |
ECMAScript 5.1 (ECMA-262) with statement |
Standard | Now forbidden in strict mode. |
ECMAScript 2015 (6th Edition, ECMA-262) with statement |
Standard |
瀏覽器兼容性
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) |
Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Basic support | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) |