ОНОВЛЕННЯ 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І ProxyAPI , були розроблені в тандемі , так що для кожної 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.getand 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об'єктів, але я не знаю, що роблять останні.