JavaScript中的解构赋值

16

从Mozilla JavaScript 1.7的更改记录中可以看出,他们添加了解构分配。 不幸的是,我对语法并不太喜欢(为什么要两次写a和b?)

var a, b;  
[a, b] = f();

类似这样的东西本来就更好:

var [a, b] = f();

那仍然是向后兼容的。类似Python的解构将不向后兼容。

无论如何,我能想到的JavaScript 1.5的最佳解决方案是:

function assign(array, map) {
    var o = Object();
    var i = 0;
    $.each(map, function(e, _) {
        o[e] = array[i++];
    });
    return o;
}

其工作方式类似于:

var array = [1,2];
var _ = assign[array, { var1: null, var2: null });
_.var1; // prints 1
_.var2; // prints 2

但这真的很糟糕,因为_没有任何意义,它只是一个空壳来存储名称。但不幸的是,它是必需的,因为JavaScript没有指针。好的一面是,在值不匹配的情况下,您可以分配默认值。还要注意,此解决方案不尝试切割数组。因此,您不能像{first:0,rest:0}这样做。但如果有人想要这种行为,那么很容易就可以做到。

有更好的解决方案吗?

4个回答

23

首先,在JavaScript 1.7中,var [a, b] = f()可以正常工作 - 试试看!

其次,你可以使用with()稍微平滑化使用语法:

var array = [1,2];
with (assign(array, { var1: null, var2: null }))
{
   var1; // == 1
   var2; // == 2
}

当然,这样做不能修改现有变量的值,所以在我看来,它比JavaScript 1.7功能要不实用得多。在我现在编写的代码中,我直接返回对象并引用其成员 - 我会等待1.7功能变得更加普遍。


2
截至今天,在Chrome中var [a,b] = [1,2];会导致语法错误。 - Marcin
9
JavaScript 1.7是一种仅限于Mozilla的语言,详见此处:https://dev59.com/xXM_5IYBdhLWcg3wjj0p。 - Shog9
3
注意,with 可能会存在安全隐患,正如 Mozilla 的官方文档 所述:“不建议使用 with,在 ECMAScript 5 严格模式下是被禁止的。推荐的替代方法是将想要访问其属性的对象分配给一个临时变量。” - Michael Mior
2
将在2015年中期左右推出ECMAScript 6版本,详情请见http://en.wikipedia.org/wiki/ECMAScript。 - pkopac
2
在严格模式下,with 也是不允许的,而严格模式是一个非常有用的模式... - T.J. Crowder
显示剩余3条评论

3
你不需要使用虚拟的“_”变量。你可以直接通过使用 window 对象范围创建“全局变量”:
window["foo"] = "bar";
alert(foo); // Gives "bar"

以下是几个要点:

  • 我不会把这个函数命名为"assign",因为那太通用了。
  • 为更接近JS 1.7语法,我会使函数将目标作为第一个参数,源作为第二个参数。
  • 使用对象字面量传递目标变量很酷,但可能会与JS 1.7解构混淆,其中目标实际上是一个对象而不是一个数组。我更喜欢使用逗号分隔的变量名称列表作为字符串。

下面是我的建议:

function destructure(dest, src) {  
    dest = dest.split(",");  

    for (var i = 0; i < src.length; i++) {  
        window[dest[i]] = src[i];  
    }  
}  

var arr = [42, 66];  

destructure("var1,var2", arr); 

alert(var1); // Gives 42
alert(var2); // Gives 66

2
我唯一同意的是解构可能是一个更好的名称。
  • 源,目标是Unix风格。
  • 填充全局范围并不好。它不会导致可组合性。
  • 将输出变量写成字符串很繁琐,也更难让您的编辑器检查。就像编写SQL一样。
- Anders Rune Jensen
@AndersRuneJensen 由于这类似于一个赋值操作,目标变量几乎肯定应该在左边 - 这样它看起来有点像 [var1,var2] = arr。而且 destructure 是一个糟糕的、不透露意图的名称。我认为 assign 更好 - 毕竟,这应该是一个通用的实用函数。如果不是,那么也许可以叫做 massAssign - Marnen Laibow-Koser

1
以下是我在 PHPstorm 10 中所做的操作:
点击 "文件" -> "设置" -> "语言和框架" -> ...
将 JavaScript 语言版本设置为例如 JavaScript 1.8.5...
点击 "应用"。

0
在标准的JavaScript中,我们习惯了各种丑陋的代码,使用一个中间变量模拟解构赋值也并不算太糟糕:
function divMod1(a, b) {
    return [ Math.floor(a / b), a % b ];
}

var _ = divMod1(11, 3);
var div = _[0];
var mod = _[1];
alert("(1) div=" + div + ", mod=" + mod );

然而,我认为以下模式更符合语言习惯:

function divMod2(a, b, callback) {
    callback(Math.floor(a / b), a % b);
}

divMod2(11, 3, function(div, mod) {
    alert("(2) div=" + div + ", mod=" + mod );
});

请注意,我们不是将两个结果作为数组返回,而是将它们作为参数传递给回调函数。
(请参见代码运行http://jsfiddle.net/vVQE3/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接