Alan Storm对我关于with声明的回答的评论引起了我的思考。我很少找到使用这个特殊语言特性的理由,也从来没有想过它可能会带来什么麻烦。现在,我很好奇如何有效地利用with,同时避免它的陷阱。
你觉得with语句在哪里有用?
Alan Storm对我关于with声明的回答的评论引起了我的思考。我很少找到使用这个特殊语言特性的理由,也从来没有想过它可能会带来什么麻烦。现在,我很好奇如何有效地利用with,同时避免它的陷阱。
你觉得with语句在哪里有用?
当前回答
当您需要将对象结构从平面转换为层次结构时,With与简写对象表示法结合使用非常有用。如果你有:
var a = {id: 123, name: 'abc', attr1: 'efg', attr2: 'zxvc', attr3: '4321'};
所以不要:
var b = {
id: a.id,
name: a.name
metadata: {name: a.name, attr1: a.attr1}
extrastuff: {attr2: a.attr2, attr3: a.attr3}
}
你可以简单地写:
with (a) {
var b = {
id,
name,
metadata: {name, attr1}
extrastuff: {attr2, attr3}
}
}
其他回答
我认为with的有用性取决于你的代码写得有多好。例如,如果你写的代码是这样的:
var sHeader = object.data.header.toString();
var sContent = object.data.content.toString();
var sFooter = object.data.footer.toString();
然后你可以这样说with可以提高代码的可读性:
var sHeader = null, sContent = null, sFooter = null;
with(object.data) {
sHeader = header.toString();
sContent = content.toString();
sFooter = content.toString();
}
相反,你可能会认为你违反了得墨忒耳定律,但是,话说回来,也许没有。我跑题了。
最重要的是,要知道Douglas Crockford建议不要使用with。我敦促你看看他的博客文章关于与它的替代品在这里。
你可以使用with来避免在使用require.js时显式地管理arity:
var modules = requirejs.declare([{
'App' : 'app/app'
}]);
require(modules.paths(), function() { with (modules.resolve(arguments)) {
App.run();
}});
requirews .declare的实现:
requirejs.declare = function(dependencyPairs) {
var pair;
var dependencyKeys = [];
var dependencyValues = [];
for (var i=0, n=dependencyPairs.length; i<n; i++) {
pair = dependencyPairs[i];
for (var key in dependencyPairs[i]) {
dependencyKeys.push(key);
dependencyValues.push(pair[key]);
break;
}
};
return {
paths : function() {
return dependencyValues;
},
resolve : function(args) {
var modules = {};
for (var i=0, n=args.length; i<n; i++) {
modules[dependencyKeys[i]] = args[i];
}
return modules;
}
}
}
它很适合将在相对复杂的环境中运行的代码放入容器中:我使用它来为“窗口”创建本地绑定,从而运行用于web浏览器的代码。
当您需要将对象结构从平面转换为层次结构时,With与简写对象表示法结合使用非常有用。如果你有:
var a = {id: 123, name: 'abc', attr1: 'efg', attr2: 'zxvc', attr3: '4321'};
所以不要:
var b = {
id: a.id,
name: a.name
metadata: {name: a.name, attr1: a.attr1}
extrastuff: {attr2: a.attr2, attr3: a.attr3}
}
你可以简单地写:
with (a) {
var b = {
id,
name,
metadata: {name, attr1}
extrastuff: {attr2, attr3}
}
}
有使用Delphi的经验,我会说使用with应该是最后的大小优化方法,可能由某种javascript最小化算法执行,并访问静态代码分析以验证其安全性。
随意使用with语句可能会遇到范围问题,这是一个非常痛苦的问题,我不希望任何人经历调试会话来弄清楚他…,却发现它捕获了一个对象成员或错误的局部变量,而不是您期望的全局变量或外部作用域变量。
VB的with语句更好,因为它需要点来消除范围的歧义,但Delphi的with语句是一把上膛的枪,带有一发之机,在我看来,javascript的with语句与之相似,足以保证同样的警告。