Как Object.defineProperty получает и устанавливает параметры для всех неизвестных дочерних элементов в object

#javascript #ecmascript-6

#javascript #ecmascript-6

Вопрос:

например, я определяю объект obj :

 var obj = {}
Object.defineProperty(obj, "a", {
  value : 37,
  writable : true,
  enumerable : true,
  configurable : true
});
console.log(obj.a); // => 37
  

Я хочу получить доступ ко всем неизвестным дочерним элементам с одинаковым значением, например obj.a.b.c.d.e / obj.c.d.e.f.e.... => 37

Комментарии:

1. Если obj.a должно быть 37, то obj.a.b должно быть 37.b значение, которое не определено…

Ответ №1:

Нет способа вернуть такое число, потому что каждое вложенное свойство должно возвращать объект, если вы хотите иметь неограниченный доступ к другим вложенным ключам — лучшее, что вы можете сделать, это вернуть объект, который может быть преобразован в желаемую строку, возможно, с помощью прокси:

 const handler = {
  get(_, prop) {
    return prop === Symbol['toPrimitive']
    ? () => '37'
    : objProx;
  }
}
const objProx = new Proxy({}, handler);

console.log(''   objProx.a); // => '37'
console.log(''   objProx.a.b); // => '37'
console.log(''   objProx.a.b.c.d.e.foobarbaz); // => '37'  

Ответ №2:

Вы могли бы создать функцию, которая принимает другую функцию в качестве параметра. И выполнить функцию внутри try...catch и вернуть значение, если оно существует, или вернуть значение по умолчанию, если произошла ошибка:

 const DEFAULT_VAL = 37;

// get a function and an optional default value to override
function getAnyDepth(func, def) {
    try {
        return func();
    } catch (e) {
        return typeof def !== "undefined" ? def : DEFAULT_VAL;
    }
}

var obj = { a: 45 }

console.log(getAnyDepth(() => obj.a))
console.log(getAnyDepth(() => obj.a.b.c.d.e))
console.log(getAnyDepth(() => obj.c.d.e, { b: 100 }))  

Ссылка: Как избежать «Не удается прочитать ‘name’ свойства undefined» в JavaScript

Ответ №3:

Если вы имеете в виду, что вам нужно значение по умолчанию каждый раз, когда вы обращаетесь к неопределенному ключу в вашем объекте, вы должны :

 _.defaults(obj, {value: 37"})
  

или вы можете использовать стандартное сравнение :

 if(typeof obj.a =='undefined'){
  return 37
}
  

Ответ №4:

Если obj.a равно 37, то obj.a.b будет вычисляться значение 37.b , которое не определено. Однако, если вас устроит, если 37 будет результатом преобразования чего-либо в примитив (например, путем конкатенации строк), тогда вы могли бы создать прокси.

ДЕМОНСТРАЦИЯ:

 // Preparation
function setDefaultProperty(obj, defProp) {
    return new Proxy(obj, {
        get(target, prop) {
            if (prop in target || typeof prop === "symbol") return target[prop];
            return target[defProp];
        }
    });
}

var sink = setDefaultProperty({}, "_default");
sink._default = sink;
sink.valueOf = () => 37;

// Demo

var obj = {};

obj = setDefaultProperty(obj, "_default");
obj._default = sink;

console.log(""   obj.a.b.c.e); // 37
console.log(""   obj.what.ever); // 37