Какие сценарии модернизатора существуют для новых функций ECMAScript 5?

ECMAScript 5 имеет довольно много хороших дополнений. У John Resig есть хороший обзор здесь. Вот хорошая таблица совместимости ECMAScript 5.

Много этого материала может "фальсифицироваться" для браузеров, которые еще не поддерживают эти функции. Вы знаете о каких-либо сценариях, которые могут сделать это? Я особенно интересуюсь Object.create.

Например, сценарий Douglas Crockford JSON проверяет, существуют ли функции JSON прежде, чем создать их.

Если бы там больше был похож на JSON один, то мы могли бы включать их, когда мы должны использовать новые функции.

16
задан Shog9 17 August 2010 в 23:36
поделиться

2 ответа

Крокфорд рекомендует такую ​​прокладку Object.create :

if (typeof Object.create != "function") {
  Object.create = function (o) {
    function F(){}
    F.prototype = o;
    return new F;
  };
}

Но, пожалуйста, не делайте этого .

Проблема с этим подходом заключается в том, что ES5 Object.create имеет подпись из 2 аргументов : первый - объект для наследования, а второй (необязательный) - объект, представляющий свойства (а точнее, дескрипторы) для добавления к вновь созданному объекту.

Object.create(O[, Properties]); // see 15.2.3.5, ECMA-262 5th ed.

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

Каковы практические последствия?

Что ж, если есть какой-то код (скажем, сторонний скрипт), который хочет использовать Object.create , то для этого кода вполне разумно сделать следующее:

if (Object.create) {
  var child = Object.create(parent, properties);
}

- по сути предполагая, что если Object.create существует, он должен соответствовать спецификациям - принять второй аргумент и добавить соответствующие свойства к объекту.

Но с вышеупомянутой прокладкой второй аргумент просто игнорируется. Нет даже указания на то, что что-то идет не так иначе. Тихий сбой, так сказать - то, что довольно болезненно обнаружить и исправить.

Можем ли мы сделать лучше?

Ну, на самом деле невозможно создать полностью соответствующую Object.create прокладку, используя только (стандартные) средства ES3 . Лучшее решение - создать собственный метод-оболочку.

Однако есть несколько альтернативных (менее оптимальных) вещей, которые вы можете попробовать:

1) Уведомить пользователя о невозможности работы со вторым аргументом

if (!Object.create) {
  Object.create = function (o) {
    if (arguments.length > 1) { 
      throw Error('second argument is not supported'); 
    }
    // ... proceed ...
  };
}

2) Попробуйте обработать второй аргумент:

if (!Object.create) {
  Object.create = function (parent, properties) {
    function F(){}
    F.prototype = parent;
    var obj = new F;
    if (properties) {
      // ... augment obj ...
    }
    return obj;
  }; 
}

Обратите внимание, что "properties" - это объект, представляющий дескрипторы свойств , а не только имена / значения свойств, и это не очень тривиально для поддержки (некоторые вещи даже невозможны, например, управление перечислимостью свойства):

Object.create(parent, {
  foo: {
    value: 'bar',
    writable: true
  },
  baz: {
    get: function(){ return 'baz getter'; },
    set: function(value){ return 'baz setter'; },
    enumerable: true
  }
});

Другое несоответствие в исходной оболочке оболочки состоит в том, что она не заботится о том, чтобы родительский объект был нулевым .

var foo = Object.create(null);

Это создает объект, [[Prototype]] которого равен null ; другими словами, объект, который не наследуется ни от чего, даже Object.prototype (от которого наследуются все собственные объекты в ECMAScript).

foo.toString; // undefined
foo.constructor; // undefined
// etc.

Это, кстати, полезно для создания «правильных» хеш-таблиц в ECMAScript.

Это поведение можно эмулировать, но только с использованием нестандартных расширений, таких как свойство "magical" __ proto __ (поэтому реализация не будет очень переносимой или надежной). Решение этой проблемы аналогично: либо полностью эмулировать реализацию ES5, либо уведомлять о несоответствии / сбое.

40
ответ дан 30 November 2019 в 15:38
поделиться

es5 - JavaScript/EcmaScript 5 in 3 - коллекция, общая на BitBucket. Object.create, в частности, легко подделывается, стал популярным благодаря Крокфорду и другим, но улучшен здесь Джастином Лавом, сосредоточившись на многих частях ES5.

3
ответ дан 30 November 2019 в 15:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: