Можно ли эмулировать неперечислимые свойства?
ES5 имеет перечислимый флаг. Пример
Пример
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor
, pd = getOwnPropertyDescriptor(Object.prototype, "toString");
assert(pd.enumerable === false, "enumerability has the wrong value");
Частичная реализация
Частичная реализация делает невозможным, если Object.keys
и Object.getOwnPropertyNames
отфильтровывать новые неперечислимые свойства с помощью shimmed Object.defineProperty
.
Введение
Это позволяет неперечислить свойства. Это явно означает, что Пример
for (var key in {}) {
assert(key !== "toString", "I should never print");
}
Это позволяет нам добавлять свойства, чтобы сказать Object.prototype
(Пример)
Object.defineProperty(Object.prototype, "toUpperCaseString", {
value: function toUpperCaseString() {
return this.toString().toUpperCase();
},
enumerable: false
});
for (var key in {}) {
assert(key !== "toUpperCaseString", "I should never print");
}
console.log(({}).toUpperCaseString()); // "[OBJECT OBJECT]"
Вопрос
Как мы можем эмулировать это в браузерах, не поддерживающих ES5?
Таблица сопоставлений браузера
В этом случае мы заботимся о потенциальном решении этого вопроса для
- IE < 9 (IE8 работает только с объектами DOM)
- Firefox 3.6
- Safari 4
- Opera 11.5 (Opera 11.6 разрешает это).
ES5-shim не имеет решения для этого.
В ES5 shim есть решение для большинства функций ES5, которые сломают ваш код, если он не работает.
Есть ли какая-либо черная магия, которую можно сделать с помощью пропиоровых IE только API? Может быть, с VBScript?
Ответы
Ответ 1
Вы можете сделать это с помощью перезаписи кода. Перепишите каждое использование for (p in o) body
в
for (p in o) {
if (!(/^__notenum_/.test(p) || o['__notenum_' + p])) {
body
}
}
а затем вы можете пометить свойства, не перечисленные, определяя свойство __notenum_...
. Чтобы быть совместимым, вам нужно было бы настроить выше, чтобы убедиться, что __notenum_propname
определен на том же уровне прототипа, что и propname
, и если вы их используете, перезапишите eval
и new Function
, чтобы переписать.
В основном это ES5/3.
Ответ 2
Partial.js Jake Verbaten является ответом на него.
Частичный .js выглядит следующим образом
/* partial non-enumerable property implementation
Adds a flag to a weakmap saying on obj foo property bar is not enumerable.
Then checks that flag in Object.keys emulation.
*/
// pd.Name :- https://github.com/Raynos/pd#pd.Name
var enumerables = pd.Name();
Object.defineProperty = function (obj, name, prop) {
if (prop.enumerable === false) {
enumerables(obj)[name] = true;
}
...
};
Object.keys = function (obj) {
var enumerabilityHash = enumerables(obj), keys = [];
for (var k in obj) {
if (obj.hasOwnProperty(k) && !enumerabilityHash[k]) {
keys.push(k);
}
}
return keys;
};
Object.getOwnPropertyNames = function (obj) {
var keys = [];
for (var k in obj) {
if (obj.hasOwnProperty(k)) {
keys.push(k);
}
}
};
Надеюсь, это поможет ребятам найти это исправление.
Ответ 3
Если вы действительно заботитесь о IE8/IE7, вы можете сделать
for (p in o) {
if (o.hasOwnProperty(p)) { body }
}
Нет реальной альтернативы "взлома", но это может быть обход для простых случаев.
Принятый ответ действительно не работает для литералов, то есть строк ""
, чисел 3
или booleans true