JavaScript with 语句的陷阱与替代方案
本文深入解析JavaScript中with语句的使用机制及其潜在风险。通过具体测试案例,揭示在with块内修改对象属性时可能出现的数值不同步问题,指出其作为隐藏Bug的隐患。文章最后推荐通过创建局部变量引用父节点来替代with语句,从而保证代码的简洁性与数据一致性。
with语句的引入与简化作用
熟悉Java和.NET开发的开发者对包或命名空间的概念应当不陌生,这一机制有效保障了代码的简洁性与可读性。JavaScript设计之初引入with语句,其初衷可能与上述概念有相似之处,旨在简化深层对象访问。例如:
代码如下:
apple.banana.candy.dog.egg.fog.god.huh.index = 0;
doSomething(apple.banana.candy.dog.egg.fog.god.huh.index); 借助with语句,上述代码可以简化为:
代码如下:
with(apple.banana.candy.dog.egg.fog.god.huh) {
c = 0;
doSomething(index);
} with语句的潜在缺陷测试
这种写法看似简洁优美,实则存在严重缺陷。接下来通过几个测试用例来验证其潜在问题。
1. 在 with 语句内部通过内部变量修改数值
代码如下:
var root = {
branch: {
node: 1
}
};
with(root.branch) {
node = 0;
// 显示 0, 正确!
alert(node);
}
// 显示 0, 正确!
alert(root.branch.node); 2. 在 with 语句内部通过对象节点修改数值
代码如下:
var root = {
branch: {
node: 1
}
};
with(root.branch) {
root.branch.node = 0;
// 显示 0, 正确!
alert(node);
}
// 显示 0, 正确!
alert(root.branch.node); 经过测试 1 和测试 2, 乍看没什么问题, 但是... 请看测试 3.
3. 在 with 语句内部通过对象父节点修改数值
代码如下:
var root = {
branch: {
node: 1
}
};
with(root.branch) {
root.branch = {
node: 0
};
// 显示 1, 错误!
alert(node);
}
// 显示 0, 正确!
alert(root.branch.node); 由上面的测试 3 可知, with 语句内部的节点父节点修改后, 不会同步到节点本身. 也就是说, 不能保证内外数值的一致性. 这是可能成为项目里面隐藏性很高的 bug.
替代方案:使用局部变量引用
那我们该怎么办呢? 接受那很长的一串逐级访问, 还是另有他法?
方法是有的. 我们可以通过别名引用父节点的方式来调用节点对象, 如:
代码如下:
var root = {
branch: {
node: 1
}
};
var quote = root.branch;
quote.node = 0;
// 显示 0, 正确!
alert(root.branch.node); 我相信很少人会用 with 语句, 也不会有很多人知道这个关键字, 但我觉得这是个有问题的语句, 压根就不应该使用, 所以写个小文记录一下.
JavaScript闭包与类(Class)的区别及适用场景对比
2026-11-05 15:48:57
JavaScript入门要学ES6吗?let与箭头函数等新特性解析
2026-11-05 14:49:16
JavaScript 8种数据类型详解:基本类型与引用类型的区别
2026-11-05 14:25:15
怎么在JavaScript中使用async/await优化Ajax异步流程
2026-11-05 13:56:15
JavaScript replace回调函数实现动态正则替换逻辑
2026-11-05 13:52:13
