Как работает объектно-связанное назначение в JavaScript - PullRequest
0 голосов
/ 13 ноября 2018

Итак, я смотрю код на этом вопросе , и я понятия не имею, как на самом деле работает это двойное назначение в одной строке:

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 голосов
/ 13 ноября 2018

следующее:

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);
0 голосов
/ 13 ноября 2018

Присвоение переменной может преобразоваться в выражение (что-то, что разрешается в определенное значение, то есть что-то, что может содержать некоторая другая переменная). Код в вопросе - запутанный способ написания:

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

Он устанавливает base[names[i]] на пустой объект, если он еще не существует, и затем он переназначает объект , на который указывает имя переменной 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...