Object.defineProperty дублирует значения свойств - PullRequest
0 голосов
/ 21 мая 2018

Я экспериментировал с некоторыми фрагментами кода ниже, и все, кажется, работает как ожидалось.Цель состояла в том, чтобы связать a.val с b.val таким образом, чтобы при изменении a.val значение b.val также автоматически менялось.

// instantiate 
var a = {}
var b = {}

// set value
a.val = 10

// check values
console.log("A.val is:", a.val) // 10
console.log("B.val is:", b.val) // undefined

// bind values
Object.defineProperties(a, {
  val: {
    configurable: true, // can be changed or deleted
    enumerable: true,   // can be iterated over
    get: ()=> this.val,
    set: (value)=> {
        this.val = value
        b.val = value
        return value
    }
  }
})

// reset value
a.val = 20

// check values
console.log("A.val is:", a.val) // 20
console.log("B.val is:", b.val) // 20

Поэтому я хотел двигаться дальше с этой концепцией и абстрагировать Object.defineProperties часть в функции.Я думал, что смогу сделать цикл for и просмотреть свойства одного объекта, вызвать Object.defineProperty.Но я столкнулся с некоторыми проблемами:

function getSet(props){
  for(var key in props){
    Object.defineProperty(props, key, {
      configurable: true, // can be changed or deleted
      enumerable: true,   // can be iterated over
      get: ()=> this[key],
      set: (value)=> {
          this[key] = value
          return value
      }
    })
  }

  return props
}

var a = getSet({name: 'the letter a', age: 12})

a.name // undefined
a.name = 'the letter a'
a.age // 'the letter a'

По сути, я случайно связал два свойства объекта, который я передавал, функции getSet.Кроме того, я стер их начальные значения.

Мой вопрос: почему это происходит, и как мне приблизиться к моей цели - связать свойства одного объекта с другим.

В ходе тестирования нескольких других возможных решений я столкнулся с ошибкой Maximum call stack size exceeded: я полагаю, что при ссылке на this в методе получения или установки, действие по получению значения из объекта, для которого я пытаюсь определить свойствазапускает вызов к получателю и циклически повторяется.Не совсем уверен, когда и почему это произойдет.

1 Ответ

0 голосов
/ 22 мая 2018

Ваш текущий код на самом деле не работает.Два главных недостатка:

  • , вы не можете использовать функции стрелок с this в литерале объекта .Значение this будет представлять собой объект модуля (в узле) или глобальный объект (window в браузерах), а не текущий объект.

    • Если он работал так, как вы ожидали, и ссылался на получателятекущего доступа (который также имел место, когда вы экспериментировали с правильным методом), вы читали бы значение a.val из a.val и записывали значение от a.val до a.val, создавая бесконечную рекурсию, которую вы испытали.Вам нужно использовать что-то другое для фактического хранения - в вашем случае, объект b является правильным решением.
    • В браузере назначение свойства name глобального объекта приведет все кстрока
  • в вашем цикле, есть только одиночная key переменная, которую функции получения / установки устанавливают вблизи .Таким образом, все они будут использовать значение в одном и том же месте магазина.

Чтобы исправить это, используйте

function getSet(proxy, store) {
  for (const key in store) {
//     ^^^^^ block scope
    Object.defineProperty(props, key, {
      configurable: true,
      enumerable: true,
      get: () => { return store[key]; },
//                        ^^^^^
      set: (value) => { store[key] = value; }
//                      ^^^^^
    });
  }
  return proxy;
}
...