一些复杂的行为与'带有'语句和调用
Some complex behaviour with 'with' statement and call
var a = ({
x: 10,
foo: function () {
function bar() {
console.log(x);
console.log(y);
console.log(this.x);
}
with (this) {
var x = 20;
var y = 30;
bar.call(this);
}
}
}).foo();
导致未定义,30,20。
如果能得到一些关于这是如何工作的逐步调试风格的解释,我们将不胜感激。
好的,首先让我们稍微简化一下代码。我已经重构出foo
是一个方法,它没有必要演示意外的行为。
function foo(a) {
// var x, y, bar - hoisting
function bar() {
console.log(x);
console.log(y);
console.log(a.x);
}
with (a) {
var x = 20;
var y = 30;
bar();
}
}
foo({x:10});
那么,当我们调用foo
时会发生什么呢?
- 执行上下文是用声明的函数和变量设置和填充的。这就是俗称的"吊装"。在
foo
中,有函数bar
、变量x
和y
(以及函数foo
本身及其参数a
,仅在我的重构版本中(。这是bar
可以访问的范围 - 执行with语句。它将当前的词法环境与基于
a
对象的词法环境进行交换,其中的任何属性现在都可以像变量一样访问 - 值CCD_ 11被分配给CCD_。这个
x
是什么?解析该标识符时,会检查a
对象,并且-哦-它有一个具有该名称的绑定!因此,我们将值放入绑定中,这将把20
放在对象的.x
属性上 - 值CCD_ 17被分配给CCD_。这个
y
是什么?再次检查当前的词法环境,但在a
对象上找不到y
属性。因此,我们继续到父环境,它包含上面创建的x
、y
和bar
变量。实际上,在这里我们找到了一个y
变量,所以我们将值30
放在该槽中 - 调用
bar
函数。同样,建立了一个新的执行上下文(如上所述(,将来自步骤1的上下文作为其父范围(这是由bar
在foo
中的词法位置决定的,当bar
函数被实例化时-词法闭包(。现在我们记录这三种兴趣表达:x
解析为foo
范围内的变量x
,该变量仍具有值undefined
y
解析为foo
范围内的变量y
,该变量包含我们刚刚分配的值30
a.x
解析为a
对象的x
属性,该属性包含我们刚刚分配的值20
通常建议您避免使用with
。太令人困惑了!
也就是说,如果我们只是注释您的代码,这可能是最简单的。为了避免歧义,我将您的匿名对象称为{}
,而不是this
。这里排序中的切换只是为了按照从上到下的执行顺序读取代码。
var a = ({
x: 10,
foo: function () {
// entering `with(this)`: all variables are searched against `{}`
// before the engine attempts to create a new variable:
with (this) {
// `var x` creates a local `x`. But, during assignment,
// `x` matches `{}.x`, so `{}.x` is set. **local `x`**
// remains `undefined`.
var x = 20;
// `y` isn't found in `{}`, so it's a local variable
var y = 30;
// execute `bar()`
bar.call(this);
}
// we're now in scope of `{}.foo()`, but not `with(this)`.
function bar() {
// local variable `x` was declared, but never defined.
console.log(x);
// local variable `y` exists in the scope of `{}.foo()`
console.log(y);
// we're still in the "macro" scope of `{}`. So, `this` refers
// to `{}`, which was changed to 20.
console.log(this.x);
}
}
}).foo();
清澈如泥?(如果可以避免的话,不要使用with
!(
相关文章:
- 带有多个elseif的Javascript if语句
- SyntaxError:'带有'语句在严格模式下无效
- 这个函数做什么以及如何在没有'带有'语句-Javascript
- 带有 OR 语句的正则表达式来检查类似情况
- ReactJS:在带有 ajax 调用的 .map() 语句完成后执行代码
- 带有多个if语句的javascript表单验证
- 需要帮助创建带有循环的if语句
- 打印出带有参数的if-else语句
- PHP、JS和带有if-else语句的代码点火器脚本
- Angulrjs:控制器不会通过带有“as”语句的工厂发送值
- 使用'break'在带有if语句的javascript开关中
- 使用带有两个变量的相同if-else语句
- 带有if语句的循环的Javascript未到达else-if语句
- 带有3个条件的JavaScript if-else语句
- 带有输入文本的 JavaScript switch 语句
- 带有复选框 (html) 的 If/Then 语句
- 带有 if 语句的 JavaScript 在 C# 后面的代码中触发按钮 asp.net
- 为什么如果带有 innerWidth 的语句不会改变它的行为
- 带有 If/else 语句的 Javascript 图像
- 使用带有 switch 语句的 jQuery 显示某些按钮