Подтвердить что ты не робот

Можно ли эмулировать неперечислимые свойства?

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?

4b9b3361

Ответ 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