来自clojure我需要编写一些javascript函数
假设我有一个函数作用于某些spec对象..我想在本地范围内引用spec中的变量,而不必编写spec.container,spec.nrow,spec.ncol。似乎没有原生支持解构,这是正确的吗?如果是这样 我如何编写如下的解包(深度1)函数? - 我真的不想在其中使用eval。
var spec = {container: {width: 900, height: 600}, nrow: 4, ncol: 5, vgap: "5px"}
function grid(spec) {
// bad..
var width = spec.container.width;
var height = spec.container.height;
var nrow = spec.nrow;
etc...
// I would prefer to write this, then have local access to nrow, width, height, etc
unpack(spec);
unpack(container);
}
由于
答案 0 :(得分:2)
您可以使用以下方法执行所需操作:
var spec = {container: {width: 900, height: 600}, nrow: 4, ncol: 5, vgap: "5px"}
function grid(obj) {
// I would prefer to write this, then have local access to nrow, width, height, etc
unpack(obj, this);
unpack(container, this);
//do stuff here...
}
function unpack(obj, dest) {
for (var key in obj) {
dest[key] = obj[key];
}
}
以下是一个工作示例:http://jsfiddle.net/Dsaaw/
答案 1 :(得分:1)
with() { }
构造是为此设计的,但它被广泛认为是危险的语言元素,因为范围冲突的规则没有明确定义。
我要么说要么使用完全限定的对象引用,要么使用逐一分配。
答案 2 :(得分:1)
我是Coffeescript的忠实粉丝,它具有“本机”解构分配,因为它编译为等效的JavaScript。我不认为有一个非常优雅的解决方案是严格纯粹的JS。 CS看起来像这样
{ nrow, container: { width, height } } = spec
编译时产生的JavaScript将是:
var height, nrow, width, _ref;
nrow = spec.nrow, _ref = spec.container, width = _ref.width, height = _ref.height;
aroth 的解决方案很简洁,实际上我会提出建议,但我认为你存在范围问题的风险。值得一试。
答案 3 :(得分:0)
如果你想用你的另一个对象扩展this
,那么aroth的解决方案是非常好的,特别是对于RobG的评论,但只是确保你知道你正在扩展什么对象。对于深层嵌套的函数(其父级不是window
),您必须说this.width
而不是spec.width
,因此在键入方面对您没有多大帮助。或者你无法传递this
而只是在window
上创建全局变量(这基本上是正在发生的事情),这可能证明了为什么这种方法可能是危险的。
如果你想在函数中使用本地范围的变量,那么我认为你几乎不得不使用eval。
function decomp(obj) {
var result = []
for(var i in obj) {
switch(typeof(obj[i])) {
case "number":
case "boolean":
case "string":
result.push("var "+i+"="+obj[i].constructor.name+"(\""+obj[i].valueOf()+"\");")
}
}
return result.join('');
}
var someObject = {
worker: function(obj) {
eval(decomp(obj));
eval(decomp(obj.container));
alert(width);
}
}
var spec = {container: {width: 900, height: 600}, nrow: 4, ncol: 5, vgap: "5px", test: true }
someObject.worker(spec)
在这里玩here
我知道你说过你不想使用eval()
但是我想不出任何其他方法来真正做你想做的事。它位于eval()
之间,扩展this
(可能是或不是window
),或者编写一个为您展开它的js预处理器。