16

В ECMAScript 5 есть немало приятных дополнений. John Resig has a good overview here. Вот хороший ECMAScript 5 compatibility table.Какие сценарии модернизатора существуют для новых функций ECMAScript 5?

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

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

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

+0

См. Также http://stackoverflow.com/questions/1890464/is-there-a-library-which-implements-new-javascript-ecmascript-5-methods-for-older/2916063#2916063 –

ответ

40

Crockford recommends этот вид 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. 

Что мы имеем это непоследовательное выполнение с 2 различными поведения. В средах с родным 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; 
    }; 
} 

Обратите внимание, что «свойство» является объектом, представляющим собственности дескрипторы, а не только имена свойств/Val ЕЭС, и это то, что это не очень тривиальная поддержки (некоторые вещи даже не представляется возможным, например, как контроль перечислимость собственности):

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

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

var foo = Object.create(null); 

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

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

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

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

+1

Моя библиотека JavaScript Xccessors ] (http://github.com/eligrey/Xccessors) предоставляет функции 'Object.defineProperty' и' Object.defineProperties', которые вы можете использовать для решения # 2. –

+10

Это очень хорошо видно, и ваши знания ES5, очевидно, прочны, но я думаю, что стоит отметить, что код Крокфорда предшествует ES5 довольно долго: первая версия 2006 года и последняя, ​​начало 2008 года. Поэтому немного неискренне предположить, что он «рекомендует» это решение для прокладки ES5. – neonski

+7

Последний раз, когда я видел, что Дуг говорил об этом, было 3 месяца назад - http: //www.slideshare.net/douglascrockford/javascript-the-good-parts-3292746/36 Это примерно через 4 месяца после официального стандартизации ES5 (в декабре 09) и определенно позже 2008 года. Но я не хочу никого обвинять (извините, если так получилось). Мы все ошибаемся. Идея состоит в том, чтобы рекомендовать против ** подхода ** и объяснить, почему. – kangax

3

es5 - JavaScript/EcmaScript 5 in 3 - коллекция, совместно используемая в BitBucket. Object.create в частности легкий, подделка, сделанный популярным by Crockford и др., Но улучшенный здесь Justin Love, фокусирующийся на многих частях ES5.

8

ES5-регулировочная шайба http://github.com/kriskowal/es5-shim/

Это был часть нарвала автономного яваскрипт окружающей среды, но был разбит на своем собственном. Это довольно чертовски зрелый и точный.

0

Если вы не против обучения библиотеки и писать некоторый код самостоятельно, вы можете найти некоторые реализации кода библиотеки ECMAScript 5 в

https://developer.mozilla.org/En/JavaScript/ECMAScript_5_support_in_Mozilla

Например, код Array.filter

А потом Крокфорд имеет JSON.parse/stringify в json2.js

https://github.com/douglascrockford/JSON-js