ОНОВЛЕННЯ 2015:
Як було відзначено 7 «s відповідь , тепер ES6 (ECMAScript 2015) була завершена, більш відповідна документація тепер доступна:
Оригінальна відповідь (для (історичного) розуміння та додаткових прикладів) :
Reflection proposal
, Здається, просунулися до проекту ECMAScript 6 специфікації . Наразі цей документ описує Reflect
методи -object та містить лише таке про сам Reflect
-object:
Об’єкт Reflect - це один звичайний об’єкт.
Значення внутрішнього слота [[Prototype]] об’єкта Reflect є стандартним вбудованим об’єктом prototype об’єкта (19.1.3).
Об'єкт Reflect не є функційним об'єктом. Він не має внутрішнього методу [[Construct]]; не можна використовувати об’єкт Reflect як конструктор з новим оператором. Об'єкт Reflect також не має внутрішнього методу [[Call]]; неможливо викликати об'єкт Reflect як функцію.
Однак у ES Harmony є коротке пояснення його мети :
Модуль “@reflect” має кілька цілей:
- Тепер, коли ми маємо модулі, модуль “@reflect” є більш природним місцем для багатьох методів відображення, раніше визначених на Object. Для цілей зворотної сумісності навряд чи статичні методи на Object зникнуть. Однак нові методи, швидше за все, слід додавати до модуля “@reflect”, а не до конструктора об’єктів.
- Природний дім для довірених осіб, уникаючи необхідності загального прив'язки проксі.
- Більшість методів у цьому модулі накладають один на один на пастки проксі. Обробники проксі потребують цих методів для зручного пересилання операцій, як показано нижче.
Отже, Reflect
об’єкт надає ряд функцій утиліти, багато з яких, схоже, перекриваються з методами ES5, визначеними в глобальному об’єкті.
Однак це насправді не пояснює, які існуючі проблеми це має намір вирішити чи яку функціональну базу додано. Я підозрював, що це може бути оброблено, і справді, наведені вище гармонійні специфікації посилаються на "ненормативну, приблизну реалізацію цих методів" .
Вивчення цього коду може дати (подальше) уявлення про його використання, але, на щастя, існує також вікі, яка викладає ряд причин, чому об'єкт Reflect є корисним :
(Я скопіював (і відформатував) наступний текст для подальшого посилання з цього джерело, оскільки вони є єдиними прикладами, які я міг знайти. Крім того, вони мають сенс, вже мають гарне пояснення і торкаються apply
прикладу запитання .)
Більш корисні значення повернення
Багато операцій у Reflect
схожі на операції ES5, визначені на Object
, такі як Reflect.getOwnPropertyDescriptor
і Reflect.defineProperty
. Однак, тоді як Object.defineProperty(obj, name, desc)
або повернеться, obj
коли властивість було успішно визначено, або викине TypeError
інше, Reflect.defineProperty(obj, name, desc)
спекулюється, щоб просто повернути логічну форму, яка вказує, чи було властивість успішно визначено чи ні. Це дозволяє вам переробляти цей код:
try {
Object.defineProperty(obj, name, desc);
} catch (e) {
}
До цього:
if (Reflect.defineProperty(obj, name, desc)) {
} else {
}
Іншими методами, які повертають такий логічний статус успіху, є Reflect.set
(оновити властивість), Reflect.deleteProperty
(видалити властивість), Reflect.preventExtensions
(зробити об’єкт нерозширюваним) та Reflect.setPrototypeOf
(оновити посилання на прототип об’єкта).
Першокласні операції
У ES5 спосіб визначити, чи obj
визначає об'єкт певне ім'я властивості чи успадковувати його, - це запис (name in obj)
. Так само для видалення властивості використовується delete obj[name]
. Хоча виділений синтаксис є приємним і коротким, це також означає, що ви повинні явно обернути ці операції у функції, коли ви хочете передати операцію як першокласне значення.
З Reflect
, ці операції можуть бути легко визначені як функції першого класу:
Reflect.has(obj, name)
це функціональний еквівалент (name in obj)
і Reflect.deleteProperty(obj, name)
є функцією , яка робить те ж саме , якdelete obj[name].
Більш надійне застосування функцій
У ES5, коли хочеться викликати функцію f
зі змінною кількістю аргументів, упакованих як масив args
і прив'язуючи this
значення до obj
, можна написати:
f.apply(obj, args)
Однак f
може бути об'єктом, який навмисно чи ненавмисно визначає власний apply
метод. Коли ви дійсно хочете переконатися, що apply
викликана вбудована функція, зазвичай пишеться:
Function.prototype.apply.call(f, obj, args)
Це не тільки багатослів'я, але це швидко стає важко зрозуміти. Тепер Reflect
ви можете зробити надійний виклик функції коротшим та легшим для розуміння способом:
Reflect.apply(f, obj, args)
Конструктори змінних аргументів
Уявіть, що ви хочете викликати функцію конструктора із змінною кількістю аргументів. У ES6, завдяки новому синтаксису поширення, можна буде писати код, як:
var obj = new F(...args)
У ES5 це важче написати, оскільки можна використовувати F.apply
або F.call
викликати функцію зі змінною кількістю аргументів, але F.construct
функція для new
функції із змінною кількістю аргументів не існує. Тепер Reflect
можна писати в ES5:
var obj = Reflect.construct(F, args)
Поведінка переадресації за замовчуванням проксі
При використанні Proxy
об'єктів для обтікання існуючих об'єктів дуже часто перехоплюють операцію, виконують щось, а потім "роблять за замовчуванням", що зазвичай застосовується до перехопленої операції до загорнутого об'єкта. Наприклад, скажімо, що я хочу просто зареєструвати всі доступні властивості до об’єкта obj
:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
}
});
Reflect
І Proxy
API , були розроблені в тандемі , так що для кожної Proxy
пастки, існує відповідний метод на Reflect
тому , що «робить річ за замовчуванням». Отже, всякий раз, коли ви виявляєте бажання "зробити за замовчуванням" річ всередині обробника проксі, правильно, що потрібно зробити, це завжди викликати відповідний метод в Reflect
об'єкті:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
return Reflect.get(target, name);
}
});
Тип повернення Reflect
методів гарантовано сумісний з типом повернення Proxy
пасток.
Керуйте цим прив'язуванням аксесуарів
У ES5 досить просто зробити загальний доступ до властивостей або оновити властивості. Наприклад:
var name = ...
obj[name]
obj[name] = value
Методи Reflect.get
and Reflect.set
дозволяють робити те ж саме, але додатково приймають як останній необов’язковий аргумент receiver
параметр, який дозволяє явно встановити this
-binding, коли властивість, яку ви отримуєте / встановлюєте, є accessor:
var name = ...
Reflect.get(obj, name, wrapper)
Reflect.set(obj, name, value, wrapper)
Це іноді корисно, коли ви обгортаєте, obj
і ви хочете, щоб будь-які власні надсилання всередині аксесуара були перенаправлені до вашої обгортки, наприклад, якщо obj
це визначено як:
var obj = {
get foo() { return this.bar(); },
bar: function() { ... }
}
Виклик Reflect.get(obj, "foo", wrapper)
призведе this.bar()
до перенаправлення на виклик wrapper
.
Уникайте спадщини __proto__
У деяких браузерах __proto__
визначається як спеціальна властивість, що надає доступ до прототипу об'єкта. ES5 стандартизував новий метод Object.getPrototypeOf(obj)
запиту прототипу. Reflect.getPrototypeOf(obj)
робить точно те саме, за винятком того, що Reflect
також визначає відповідний Reflect.setPrototypeOf(obj, newProto)
для встановлення прототипу об'єкта. Це новий спосіб оновлення прототипу об’єкта, сумісний з ES6.
Зверніть увагу , що: setPrototypeOf
також існує наObject
(як правильно вказав КНС «s коментар )!
РЕДАГУВАТИ:
Додаткова примітка (звернення до коментарів до Q): Короткий і простий відповідь на "Q: Модулі ES6 проти імпорту HTML", що пояснює Realms
та Loader
об'єкти.
Інше пояснення пропонується за цим посиланням :
Об'єкт сфери абстрагується від поняття окремого глобального середовища, із власним глобальним об'єктом, копією стандартної бібліотеки та "властивостями" (стандартними об'єктами, які не прив'язані до глобальних змінних, наприклад, початкове значення Object.prototype).
Розширювана мережа : це динамічний еквівалент того самого походження
<iframe>
без DOM.
Хоча варто згадати: все це все ще у проекті, це не специфікація, закарбована в камені! Це ES6, тому пам’ятайте про сумісність браузера!
Сподіваюся, це допомагає!
Reflect
це просто контейнер дляRealm
іLoader
об'єктів, але я не знаю, що роблять останні.