Object.defineProperty в ES5?

Я вижу сообщения о "новом" объекте Object.create, который позволяет настраивать перечисление. Однако он опирается на метод Object.defineProperty. Я не могу найти реализацию перекрестного браузера для этого метода.

Мы застряли писать для старого объекта Object.create? Я не могу писать вещи, которые не будут работать в IE6/7.

Ответы

Ответ 1

Есть несколько вещей, которые нельзя эмулировать из метода ECMAScript 5 Object.create в среде ECMAScript 3.

Как вы видели, аргумент свойств даст вам проблемы, поскольку в реализациях на основе E3 существует no way для изменения атрибутов свойств.

Метод Object.defineProperty, упомянутый как @Raynos, работает на IE8, но частично, его можно использовать только в элементах DOM.

Также свойства аксессора дадут вам проблемы, их можно было бы имитировать с помощью широко распространенных нестандартных методов, таких как __defineGetter__/__defineSetter__, но вы не можете изменить атрибуты свойств.

Другая проблема, помимо дескрипторов свойств, заключается в том, что метод Object.create может принимать null в качестве аргумента, чтобы создать объект, который не наследует ничего.

Эту нельзя эмулировать с помощью Crockford Object.create shim, потому что когда оператор new используется с конструкторской функцией, которая имеет свойство prototype, содержащее null или любое другое значение, отличное от объекта, но созданный объект по умолчанию будет наследовать от Object.prototype.

В некоторых реализациях -V8, Spidermonkey, Rhino и т.д. - они имеют свойство setteable __proto__, которое может быть использовано для установите null [[Prototype]], но опять же, это нестандартное, и наверняка он никогда не будет работать в IE.

Я бы рекомендовал, если вы хотите настроить таргетинг на старые браузеры, чтобы не использовать эти функции, поскольку нет способа заставить их работать должным образом в этих средах.

Если вы все еще хотите использовать Object.create, не используя аргумент свойств, вы могли бы, однако, я бы рекомендовал вам обнаружить вещи, которые нельзя эмулировать.

Ниже приведена более безопасная версия Crockford Object.create shim:

if (typeof Object.create != 'function') {
  (function () {
    var F = function () {};
    Object.create = function (o) {
      if (arguments.length > 1) { throw Error('Second argument not supported');}
      if (o === null) { throw Error('Cannot set a null [[Prototype]]');}
      if (typeof o != 'object') { throw TypeError('Argument must be an object');}
      F.prototype = o;
      return new F;
    };
  })();
}

В любом случае, используйте его осторожно.

Ответ 2

Если вам нужна хорошая реализация defineProperty(), посмотрите https://github.com/kriskowal/es5-shim

К сожалению, вы не можете настроить перечисление в среде ES3. Эта прокладка позволит вам вызвать API в любой среде, но свойства будут по-прежнему перечислимы под ES3.

Ответ 3

Для чего это стоит,

Object.defineProperty работает в ie8 и FF4.

Это означает, что стоит использовать sniff и реализовать его там, где это полезно, поскольку вы надеетесь, что обновление с 6/7 до 8/9 произойдет в ближайшие несколько лет.

Еще одна вещь, о которой стоит опасаться, заключается в том, что свойство dontEnum имеет ошибку в JScript

Вам придется работать так, как вы используете свойство dontEnum в IE.

[Изменить]:

Здесь документация для Internet explorer и ссылка на спецификация ES5 (Страница 122, 15.2.3.6)