不建议使用with
语句,因为它可能是混淆错误和兼容性问题的根源。有关详细信息,请参阅下面“说明”一节中的“歧义对比”部分。
with语句 扩展一个语句的作用域链。
语法节
<span style="color:#333333">with (expression) {
<em>statement</em>
}
</span>
expression
将给定的表达式添加到在评估语句时使用的作用域链上。表达式周围的括号是必需的。
statement
任何语句。要执行多个语句,请使用一个块语句 ({ ... })对这些语句进行分组。
描述节
JavaScript查找某个未使用命名空间的变量时,会通过作用域链来查找,作用域链是跟执行代码的context或者包含这个变量的函数有关。'with'语句將某个对象添加的作用域链的顶部,如果在statement中有某个未使用命名空间的变量,跟作用域链中的某个属性同名,则这个变量将指向这个属性值。如果沒有同名的属性,则将拋出ReferenceError
异常。
不推荐使用with
,在 ECMAScript 5 严格模式中该标签已被禁止。推荐的替代方案是声明一个临时变量来承载你所需要的属性。
性能方面的利与弊节
利:with
语句可以在不造成性能损失的情況下,减少变量的长度。其造成的附加计算量很少。使用'with'可以减少不必要的指针路径解析运算。需要注意的是,很多情況下,也可以不使用with语句,而是使用一个临时变量来保存指针,来达到同样的效果。
弊:with
语句使得程序在查找变量值时,都是先在指定的对象中查找。所以那些本来不是这个对象的属性的变量,查找起来将会很慢。如果是在对性能要求较高的场合,'with'下面的statement语句中的变量,只应该包含这个指定对象的属性。
语义不明的弊端节
弊端:with
语句使得代码不易阅读,同时使得JavaScript编译器难以在作用域链上查找某个变量,难以决定应该在哪个对象上来取值。请看下面的例子:
<span style="color:#333333"><code class="language-js"><span style="color:#0077aa">function</span> <span style="color:#dd4a68">f</span><span style="color:#999999">(</span>x<span style="color:#999999">,</span> o<span style="color:#999999">)</span> <span style="color:#999999">{</span>
<span style="color:#0077aa">with</span> <span style="color:#999999">(</span>o<span style="color:#999999">)</span>
<span style="color:#dd4a68">print</span><span style="color:#999999">(</span>x<span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span></code></span>
f
被调用时,x
有可能能取到值,也可能是undefined
,如果能取到, 有可能是在o上取的值,也可能是函数的第一个参数x
的值(如果o中没有这个属性的话)。如果你忘记在作为第二个参数的对象o中定义x
这个属性,程序并不会报错,只是取到另一个值而已。
弊端:使用with
语句的代码,无法向前兼容,特別是在使用一些原生数据类型的时候。看下面的例子:
<span style="color:#333333"><span style="color:#333333"><code class="language-js"><span style="color:#0077aa">function</span> <span style="color:#dd4a68">f</span><span style="color:#999999">(</span>foo<span style="color:#999999">,</span> values<span style="color:#999999">)</span> <span style="color:#999999">{</span>
<span style="color:#0077aa">with</span> <span style="color:#999999">(</span>foo<span style="color:#999999">)</span> <span style="color:#999999">{</span>
console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span>values<span style="color:#999999">)</span>
<span style="color:#999999">}</span>
<span style="color:#999999">}</span></code></span></span>
如果是在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
函数,不用在前面添加命名空间。
<span style="color:#333333"><code class="language-js"><span style="color:#0077aa">var</span> a<span style="color:#999999">,</span> x<span style="color:#999999">,</span> y<span style="color:#999999">;</span>
<span style="color:#0077aa">var</span> r <span style="color:#9a6e3a">=</span> <span style="color:#990055">10</span><span style="color:#999999">;</span>
<span style="color:#0077aa">with</span> <span style="color:#999999">(</span>Math<span style="color:#999999">)</span> <span style="color:#999999">{</span>
a <span style="color:#9a6e3a">=</span> <span style="color:#990055">PI</span> <span style="color:#9a6e3a">*</span> r <span style="color:#9a6e3a">*</span> r<span style="color:#999999">;</span>
x <span style="color:#9a6e3a">=</span> r <span style="color:#9a6e3a">*</span> <span style="color:#dd4a68">cos</span><span style="color:#999999">(</span><span style="color:#990055">PI</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
y <span style="color:#9a6e3a">=</span> r <span style="color:#9a6e3a">*</span> <span style="color:#dd4a68">sin</span><span style="color:#999999">(</span><span style="color:#990055">PI</span> <span style="color:#9a6e3a">/</span> <span style="color:#990055">2</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span></code></span>
规范节
Specification | Status | Comment |
---|---|---|
ECMAScript Latest Draft (ECMA-262) with statement |
Draft | |
ECMAScript 2015 (6th Edition, ECMA-262) with statement |
Standard | |
ECMAScript 5.1 (ECMA-262) with statement |
Standard | Now forbidden in strict mode. |
ECMAScript 3rd Edition (ECMA-262) with statement |
Standard | |
ECMAScript 1st Edition (ECMA-262) with statement |
Standard | Initial definition |
浏览器兼容节
Update compatibility data on GitHub
Desktop | Mobile | Server | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Chrome | Edge | Firefox | Internet Explorer | Opera | Safari | Android webview | Chrome for Android | Edge Mobile | Firefox for Android | Opera for Android | Safari on iOS | Samsung Internet | Node.js | |
Basic support Deprecated |
Full supportYes | Full supportYes | Full support1 | Full supportYes | Full supportYes | Full supportYes | Full supportYes | Full supportYes | Full supportYes | Full support4 | Full supportYes | Full supportYes | Full supportYes | Full supportYes |
Legend
Full support
Full support
Deprecated. Not for use in new websites.
Deprecated. Not for use in new websites.
相关链接节
原文地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/with