Обновление: Поскольку вопрос остался без ответа, я немного меняю его. Комментарии к записи в блоге Дина, ссылка на которую приведена ниже, показывают, что эта техника не работает в Safari.
Теперь мой вопрос таков: работает ли описанная ниже техника* в современных браузерах, и, в частности, может ли кто-нибудь подтвердить, работает ли она в Safari?
Вот более свежий пост в блоге. В одном месте говорится:
Sandboxed natives ... поддерживается в различных браузерах, включая ... Safari 2.0+
... но позже говорится, что техника iframe "поддерживается всеми основными браузерами, кроме Safari", а показанный им запасной вариант включает в себя какие-то странные вещи с поддельными конструкторами и __proto__
, которые кажутся немного халтурными.
Мне почти трудно поверить, что два разных окна могут иметь один и тот же, скажем, прототип Object.prototype. Что происходит с междоменными iframe? Если я изменяю прототипы в одном фрейме, будут ли изменены прототипы в другом фрейме? Это кажется очевидной проблемой безопасности. Кто-нибудь, пожалуйста, пролейте свет на эту ситуацию.
* Под "работать" я подразумеваю My.Object != Object
, так что прототипы могут быть изменены в одном окне, не затрагивая другое.
Оригинальное сообщение
Я знаю, что об этом уже спрашивали, но у меня есть конкретное решение, и я хочу знать, обсуждался ли этот тип решения раньше, и где я могу узнать, насколько он надежен и хорошо принят.
Вопрос в том, как расширить нативные типы в javascript, не изменяя сами типы, так что простое изменение Array.prototype не подходит (возможно, в другом коде используется for..in с массивами). Создание поддельного конструктора, который возвращает родной массив с добавлением некоторых функций, тоже не кажется хорошим решением, лучше действительно расширить родные объекты. Но вы также не можете сделать обычное расширение в стиле javascript с фиктивным прототипом функции switcharoo с родными типами, потому что вы получите ошибки типа "push is not generic", когда попытаетесь вызвать родные функции.
Итак, решение, которое я имею в виду, работает следующим образом: создайте другое окно, добавьте функциональность к прототипам нативных конструкторов в этом окне, и используйте эти конструкторы в своей программе.
Этот пример расширяет Array
как My.Array
с функцией each
и String
как My.String
с функцией alert
.
var My = (function(){
// create an iframe to get a separate global scope
var iframe = document.createElement('iframe');
iframe.style.height = '0px';
iframe.style.width = '0px';
iframe.style.border = 'none';
iframe.style.position = 'absolute';
iframe.style.left = '-99999px';
document.documentElement.appendChild(iframe);
var My = iframe.contentWindow;
My.String.prototype.alert = function(){
alert(this);
}
My.Array.prototype.each = function(callback){
for (var i=0, l=this.length; i
Опять же, мой вопрос в том, обсуждался ли этот подход раньше, как он называется, где я могу найти больше информации и т.д. Я хотел бы знать, есть ли более чистый способ получить другую глобальную область видимости без использования iframe, или возможно ли, что это не сработает по какой-то причине в некоторых javascript-движках, или если кто-то считает, что это особенно плохая идея, или что-то еще.
Обновление: я полагаю, что люди называют такие вещи iframe sandbox, не путать с атрибутом HTML5 iframe sandbox.
related:
http://dean.edwards.name/weblog/2006/11/hooray/
http://webreflection.blogspot.com/2008/03/javascript-arrayobject.html