JavaScript объектов, определенных по-разному - PullRequest
0 голосов
/ 21 февраля 2020

Я довольно новичок в JavaScript и у меня есть вопрос относительно того, как объекты определены в следующем фрагменте кода.

В первом случае domStrings объект определяется как domStrings=, а во втором Например, возвращаемый объект определяется как getinput:function() в чем разница? И почему, если я изменяю возвращаемый объект как getinput=function, он не работает? Пожалуйста, помогите мне понять.

var UIcontroller = (function() {
  var domStrings = {
    inputType: '.add__type',
    inputDescription: '.add__description',
    inputValue: '.add__value',
    addButton: '.add__btn'
  }
  return {
    getinput: function() {
      return {
        type: document.querySelector(domStrings.inputType).value,
        description: document.querySelector(domStrings.inputDescription).value,
        value: document.querySelector(domStrings.inputValue).value
      };
    },

    getDomStrings: function() {
      return domStrings;
    }
  }
})();

Ответы [ 3 ]

0 голосов
/ 21 февраля 2020

Это присваивание и объявление двух вещей:

var domStrings = {
    inputType: '.add__type',
    inputDescription: '.add__description',
    inputValue: '.add__value',
    addButton: '.add__btn'
  }

Переменная domstrings объявлена ​​var domStrings и присвоена =.

Переменная теперь указывает на место в памяти. В этом месте в памяти находится объект, который только что был создан.

Объект в JavaScript - это словарь: это набор пар ключ: значение, где ключом может быть строка или число (или символ, но пока не беспокойтесь об этом) ).

Синтаксис для объявления объекта: {'key': 'value' ....}.

Значением может быть любой из типов JS, поэтому в основном, строка, число, пустота, функция или другой объект.

Вы можете указать другую переменную на тот же объект в памяти:

var a = domStrings;
a.inputType /// '.add__type'

Если я теперь назначу что-то еще domStrings:

domStrings = "nope"

domStrings теперь указывает на другое место в памяти:

domStrings.inputType // undefined - "nope" doesn't have a property inputType

a все еще указывает на объект:

a.inputType // '.add__type'

Так что это утверждение делает больше, чем одну вещь. Он объявляет переменную domStrings, создает объект в памяти и присваивает объект domStrings, так что domStrings является ссылкой на объект.

Это делает эту часть более понятной?

Вторая часть:

То, на что вы смотрите, называется закрытием. Это IIFE - «немедленное выполнение функции» - немедленно выполняемая функция, которая создает нечто вроде сингулярности вокруг черной дыры. Все внутренние механизмы внутри этого замыкания функции могут видеть, что там, но значение UIController извне равно:

{
  getinput:() => {...},
  getDomStrings: () => domstrings
}

Функция getDomStrings внутри UIController может видеть переменную domstrings и передать указатель на него обратно к коду снаружи, но это единственный способ, чтобы все, что находится вне замыкания, могло получить к нему доступ.

Функция getInput также может видеть его и использует для вычисления объекта, который он возвращается при вызове.

Таким образом, вы можете обмениваться кодом / данными между функциями внутри замыкания, но единственный способ увидеть что-либо вне замыкания - это если вы передаете ссылку, как getDomStrings.

Это не очень безопасно, потому что что-то вне этого замыкания может вызвать getDomStrings и получить ссылку на объект. Затем он может изменить значения в объекте, что изменит поведение функции getInput непредсказуемым образом.

Похоже, что автор хотел, чтобы люди могли прочитать его этот объект, но не получить доступ это изменить его - в этом случае способ сделать это - вернуть копию объекта. Это дает вызывающей стороне объект с теми же значениями, но не в той же области памяти. Изменение копии не изменит объект внутри замыкания.

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

Я думаю, что это первый, потому что у него есть get, но не соответствующий set метод.

Поскольку объект - это место в памяти, а объекты может быть вложенным, копирование объекта не тривиально. Вы должны сделать копию всех объектов внутри него.

Проверьте это:

const a = {z: 3, k: {a: 3}}
const b = {...a} // "Spread" the keys of a onto b, a "shallow copy"

> b
{ z: 3, k: { a: 3 } } // looks b is a copy of a

> b.k.a = 4  // change a "deep value" of b
> b
{ z: 3, k: { a: 4 } }
> a
{ z: 3, k: { a: 4 } } // the object in a has changed!

> b.z = 2 // change a shallow property of b
> b
{ z: 2, k: { a: 4 } } // b has changed
> a
{ z: 3, k: { a: 4 } } // a has not

Здесь произошло то, что объекты a и b находятся в другой памяти местах. Однако каждый из этих объектов имеет свойство k, которое указывает на другое местоположение, и они указывают на одно и то же местоположение!

Мы можем проверить это:

> a == b
false
> a.k === b.k
true // !

Итак, возвращаем domStrings from getDomStrings фактически позволяет коду вне этого контроллера изменять его поведение.

В этом случае будет работать возврат спреда, потому что domStrings не имеет ключей, которым назначены ссылки на объекты.

Я бы написал это как:

getDomStrings: function() {
   return {...domStrings};
}

Возвращает копию с такими же значениями, чтобы другие части программы могли использовать их для поиска, принятия решений или выбора; но эту копию нельзя использовать, чтобы связываться с тем, что находится внутри замыкания.

Вот вам go, урок по ссылкам на объекты в JS, который вы не просили. Добро пожаловать!

0 голосов
/ 21 февраля 2020

То, что вы смотрите, называется выражением немедленно вызванной функции (или IIFE, произносится как «iffy») . Это обходной путь для (ECMAScript 5) JavaScript, чтобы избежать подъема и создания замыканий.

В вашем примере переменная domString назначается с использованием знака равенства, а часть справа называется объектом литерал и использует объект литеральный синтаксис. Две функции, возвращаемые в операторе return, объявляются как свойства, не отличающиеся от, например, объекта литерал domStrings inputType:. Разница в том, что значения свойств в литерале объекта оператора return являются функциями, а не строками. Переменные и свойства объекта в JavaScript могут содержать функции в качестве своих значений.

В вашем примере: domStrings является частным свойством функции UIcontroller и недоступно откуда-либо еще, кроме как внутри функции UIcontroller. Он предоставляет две функции publi c: getDomStrings и getinput и возвращает их для использования вызывающими при создании экземпляра.

Эти два метода имеют доступ к domStrings, но за пределами функции UIcontroller больше ничего не происходит, кроме случаев, когда вы возвращаете ссылка на domString в операторе возврата.

Вы можете вызвать UIcontroller.getDomStrings () и UIcontroller.getinput (), но вы не можете вызвать UIcontroller.domStrings. Возврат domStrings в операторе return сделает его доступным c свойством UIcontroller, которое любой может изменить в любом месте.

Надеюсь, это поможет. Это вам ответит?

Удачного кодирования !!!

0 голосов
/ 21 февраля 2020

var domStrings - это object, объекты имеют ключи и значения. inputType, inputDescription, inputValue, addButton - ключи, справа от них - их значения. Вы можете получить к ним доступ, выполнив domStrings.inputType et c ..

ваша функция возвращает другой объект return {}, поэтому getinput на самом деле является ключом для этого объекта, поэтому он определен так

...