2011-05-23 1 views
5

Я пытаюсь определить пользовательский сеттер для свойства innerHTML. К сожалению, я не в состоянии получить доступ к основному свойству после того, как я определить функцию сеттера:Доступ к свойствам, скрытым __defineGetter __/__ defineSetter__ в JavaScript

$('body')[0].__defineSetter__("innerHTML", 
    function (val) { 
    alert("Setting to: " + val); 
    this.innerHTML = val; 
}); 

Этого фрагмент кода заполняет стек вызовов, поскольку назначение вызывает сеттер рекурсивно. Apparenly innerHTML уже перегружен в IE8, и вы можете просто сохранить старшую пару get/set и использовать его в новом дескрипторе свойства. Взято из MSDN:

var innerHTMLdescriptor = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML'); 
Object.defineProperty(Element.prototype, 'innerHTML', 
    { set: function(htmlVal) { 
     var safeHTML = toStaticHTML(htmlVal); 
     innerHTMLdescriptor.set.call(this, safeHTML); 
    } 
}); 

Однако, это, кажется, не тот случай для Chrome, где getOwnPropertyDescriptor возвращает неопределенное значение для innerHTML. В этом случае, как мне получить доступ к базовому свойству?

Вопрос с бонусом: как я могу гарантировать, что все объекты, созданные в будущем, имеют это специальное поведение innerHTML? Можно ли использовать для этого прототипы DOM? Кажется, что перегрузка функции не то, что мне нужно здесь. Возможно, можно перегрузить конструктор DOM и добавить вызов __defineGetter__/defineProperty, но похоже, что поддержка конструкторов не распространена, поэтому я хотел бы знать, есть ли какая-либо альтернатива.

+0

Не используйте \ _ \ _ defineSetter \ _ \ _ в фактическом производственном коде - он нестандартен и может исключать пользователей из многих браузеров. – Ryan

+1

стандартным эквивалентом является 'defineProperty' право? тем не менее, проблема ссылки на скрытое свойство существует ... – BruceBerry

+1

Нет, это по-прежнему не стандарт. Вы не должны использовать его, потому что он исключает старые браузеры. Конечно, если вы делаете что-то неважное и оно грамотно деградирует, все в порядке. Но это не похоже на то, что будет в вашем случае. – Ryan

ответ

1

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

var _innerHTML = ""; 

this.__defineSetter__("innerHTML", 
    function (val) { 
     alert("Setting to: " + val); 
     _innerHTML = val; 
    }); 

this.__defineGetter__("innerHTML", 
    function() { 
     return _innerHTML; 
    }); 

Однако, я обнаружил, что с помощью методов получения и установки на существующих свойств DOM часто просто не будет работать, благодаря специальной обработке этих свойств внутренне. Например, он не будет работать с свойством value текста input. Я ожидал бы, что innerHTML будет в одной лодке.

Смежные вопросы