对象链接分配如何在javascript中工作

时间:2018-11-13 02:21:54

标签: javascript loops object

所以我正在看this question上的一些代码,我不知道一行中的这种双重分配实际上是如何工作的:

var deepAssign = function( base, names, value ) {
    // If a value is given, remove the last name and keep it for later:
    var lastName = arguments.length === 3 ? names.pop() : false;

    // Walk the hierarchy, creating new objects where needed.
    // If the lastName was removed, then the last object is not set yet:
    for( var i = 0; i < names.length; i++ ) {
        base = base[ names[i] ] = base[ names[i] ] || {}; /* this line wtf? */
    }

    // If a value was given, set it to the last name:
    if( lastName ) base = base[ lastName ] = value;

    // Return the last object in the hierarchy:
    return base;
};
var x = {}
deepAssign(x, ['a', 'b', 'c'])
console.log(x) /* wtf, how? => { a: { b: { c: {} } } } */

我认为原始的“基础”对象将在for循环中被破坏,然后“基础”将仅是内部对象,但是以某种方式保留了传入的原始对象。有人可以详细解释一下for循环中发生的事情吗?在代码内部有一些我不理解的东西真的使我感到困扰。

2 个答案:

答案 0 :(得分:0)

变量赋值可以解析为表达式(可以解析为特定值的东西-即某些其他变量可以容纳的东西)。问题中的代码是一种令人困惑的编写方式:

for( var i = 0; i < names.length; i++ ) {
    base[ names[i] ] = base[ names[i] ] || {};
    base = base[ names[i] ];
}

它将base[names[i]]设置为空对象(如果尚不存在),然后将 object 重新分配给变量名base指向该内部对象。 (base最初引用的外部对象仍然存在,只是不再有引用它的特定变量-尽管仍然可以通过使用最外部x对象的标准属性访问来获得它) )。

如果您熟悉数组方法,则reduce在这种情况下会更合适并且更容易阅读:但是,将累加器作为当前的外部对象,如果不存在则创建内部对象并在下一次迭代中将内部对象返回为新的累加器:

function assign(outermost, keyPath, value) {
  const lastKey = keyPath.pop();
  const innermostObj = keyPath.reduce((outer, prop) => {
    outer[prop] = outer[prop] || {};
    return outer[prop];
  }, outermost)
  innermostObj[lastKey] = value;
}

const settings = {};
assign(settings, ['Modules', 'Video', 'Plugin'], 'JWPlayer');
console.log(settings);

答案 1 :(得分:0)

以下内容:

base = base[ names[i] ] = base[ names[i] ] || {};

已翻译为:

base[ names[i] ] = base[ names[i] ] || {};
base = base[ names[i] ];

此循环:

for( var i = 0; i < names.length; i++ ) {
    base = base[ names[i] ] = base[ names[i] ] || {}; /* this line wtf? */
}

被翻译为:

names.reduce((a, name) => (a[name] || (a[name] = {})), base);

基本上,在键name不存在时创建对象,但这是检查键是否存在的危险方式。

这是使用运算符in的更好方法:

names.reduce((a, name) => (name in a ? a[name] : (a[name] = {})), base);