Более глубокое понимание механизмов модулей в Javascript - PullRequest
1 голос
/ 27 мая 2020

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

Наблюдение а. Все модули в JavaScript по умолчанию являются одиночными, поэтому

// module a.js
let notification = 10;
export default notification;

Предполагается, что у нас есть модуль b. js и c. js, и мы импортируем туда уведомление. js будет разделен. Уведомление будет доступно только для чтения.

Замечание b. Если функция экспортируется из модуля, который возвращает объект, создается новый объект.

// module a.js
let notification = 10;
export default () => ({
 notification
})

//somewhere in module b.js
import Fn from 'a.js'
let n = Fn().notification; // a new number is created since numbers are immutable in javascript but is this the reason why notification from a.js stays the same?
n = n + 10; // outputs 20

//somewhere in module c.js
import Fn from 'a.js'
let n = Fn().notification; // outputs 10

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

Наблюдение c. Если мы хотим разделить значение в модуле, нам нужно следовать следующему шаблону?

   //module a.js
    let notification = 10;
    export default () => ({
     notification,
     setNotification() {
       notification += 10;
     }
    })

Если setNotification вызывается в одном из импортированных модулей, тогда автоматически значение уведомления будет 20 везде, где еще импортируется модуль a.

Может кто-то сбросил немного света на то, почему это происходит, и верны ли мои наблюдения?

1 Ответ

2 голосов
/ 27 мая 2020

Насколько я понимаю, это происходит из-за того, что каждый раз создается новый объект?

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

Если мы хотим поделиться значением в модуле нам нужно следовать следующему шаблону?

Это будет работать, но вам необязательно делать это таким образом. Это работает так же хорошо:

export default {
    notification: 10
};

В другом модуле:

import obj from "./a.js";
console.log(obj.notification); // 10
obj.notification = 20;
console.log(obj.notification); // 20

Если после приведенного выше кода у вас есть третий импорт модуля и его использование, они вы увидите 20:

import obj from "./a.js";
console.log(obj.notification); // 20

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

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

source.js:

export let notification = 10;
export function setNotification(n) {
    notification = n;
};

a.js:

import { notification, setNotification } from "./source.js";
console.log(notification); // 10
setNotification(20);

b.js:

import { notification, setNotification } from "./source.js";
console.log(notification); // 20

main.js:

import "./a.js";
import "./b.js";

Импортированную привязку можно рассматривать как действительно эффективный получатель (средство доступа) для привязки в модуле экспорта.

Обратите внимание, что порядок, в котором выполняются a.js и b.js, и, следовательно, значения, которые они видят, определяется порядком, в котором main.js импортированы из них (а также тем фактом, что они не имеют никаких циклических ссылок или динамических c импорт в них).

...