with 语句
- 源码地址:
src\compiler\codegen\index.js
- 描述:使用 with 生成代码
源码
1 |
|
解析
[with 语法]
with 语句 扩展一个语句的作用域链
注:不建议使用 with 语句,他存在兼容性问题,且降低了代码的可读性,容易产生混淆错误。
1 |
|
express
- 将给定的表达式添加到在评估语句时使用的作用域链上。
statement
- 任意语句。
[with 语句描述]
Javascript 查找某个未使用命名空间的变量时,会通过作用域链来查找,作用域链是跟执行代码的 context 或者包含这些变量的函数有关。
‘with’ 语句将某个对象添加到作用域链的顶部,如果 statement 中有某个未使用命名空间的变量,根作用域链中的某个属性同名,则这个变量将指向这个属性值。如果没有同名的属性,则抛出 RefrenceError
异常。
备注:
使用 with 语句后,变量会先在 express 对象中查找是否有相同名称的属性,如果没有则会向外层作用域查找。
如果检查到 window 对象时,仍没有则抛出RefrenceError
异常。
ReferenceError(引用错误): 对象代表当一个不存在的变量被引用时发生的错误。
[性能方面的利弊]
利:
- with 语句可以在不造成性能损失的情况下,减少变量长度,其造成的附加计算量很少。
- 使用 with 可以减少不必要的之臣路径解析运算
注: 很多情况下,也可以不使用 with 语句,而是使用一个临时变量和来保存指针,来达到同样的效果。
弊:
with 语句使得程序在查找变量时,都是现在指定的对象中查找,所以那些本不是这个对象的属性的变量,查找起来会很慢。
如果是针对性能要求较高的场合,with 下面的 statement 语句中的变量,只应该包含这个指定对象的属性
[语意不明的弊端]
弊端一:
- with 语句使得代码不易于阅读,同时使得 Javascript 编译器难以在作用域链上查找某个变量,难以决定应该在那个对象上来取值。
1 |
|
f 被调用是,x 有可能取到值,也可能是 undefined
如果能取到,有可能是在 o 上取到的值,也可能是函数的第一个参数 x 的值(如果 o 中没有这个属性的话)
如果你忘记在作为第二个参数的对象 o 中定义 x 这个属性,程序不会报错,只是取到另一个值而已
弊端二:
- 使用 with 语句的代码,无法向前兼容,特别是使用一些原生数据类型的时候。
1 |
|
如果是在 ECMAScript 5 环境调用 f([1,2,3], obj), 则 with 语句中变量 values 指向函数的第二个参数 values.
但在 ECMAScript 6 标准给 Array.prototype 添加了一个新属性 values, 所有数组实例都继承这个属性。所以在 ECMAScript 6 环境中,with 语句中变量 values 将指向
[1,2,3].values
示例
下面的 with 语句指定 Math 对象作为默认对象。
with 语里面的变量,分别指向 Math 对象的 PI、cos 和 sin 函数,不用在前面添加命名空间。
后续所有引用都指向 Math 对象
1 |
|
语言规范
12.10 The with Statement
Syntax
WithStatement :
with ( Expression ) Statement
The with statement adds an object environment record for a computed object to the lexical environment of the current execution context. It then executes a statement using this augmented lexical environment. Finally, it restores the original lexical environment.Semantics
The production WithStatement : with ( Expression ) Statement is evaluated as follows:
- Let val be the result of evaluating Expression.
- Let obj be ToObject(GetValue(val)).
- Let oldEnv be the running execution context’s LexicalEnvironment.
- Let newEnv be the result of calling NewObjectEnvironment passing obj and oldEnv as the arguments.
- Set the provideThis flag of newEnv to true.
- Set the running execution context’s LexicalEnvironment to newEnv.
- Let C be the result of evaluating Statement but if an exception is thrown during the evaluation, let C be (throw, V, empty), where V is the exception. (Execution now proceeds as if no exception were thrown.)
- Set the running execution context’s Lexical Environment to oldEnv.
- Return C.
NOTE
No matter how control leaves the embedded Statement, whether normally or by some form of abrupt completion or exception, the LexicalEnvironment is always restored to its former state.