在 JavaScript 中访问被 __defineGetter__/__defineSetter__ 隐藏的属性

Posted

技术标签:

【中文标题】在 JavaScript 中访问被 __defineGetter__/__defineSetter__ 隐藏的属性【英文标题】:Accessing properties hidden by __defineGetter__/__defineSetter__ in JavaScript 【发布时间】:2011-08-31 12:32:51 【问题描述】:

我正在尝试为 innerhtml 属性定义自定义设置器。不幸的是,在我定义了 setter 函数后,我无法访问底层属性:

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

这个 sn-p 填充调用堆栈,因为赋值递归地调用 setter。 显然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 似乎并非如此,其中getOwnPropertyDescriptorinnerHTML 返回未定义。在这种情况下,如何访问底层属性?

额外问题:如何确保将来创建的所有对象都具有这种特殊的innerHTML 行为?是否可以为此使用 DOM 原型?似乎重载函数不是我在这里需要的。也许可以重载 DOM 构造函数并添加一个调用 __defineGetter__/defineProperty 但看起来对构造函数的支持并不常见,所以我想知道是否有任何替代方法。

【问题讨论】:

不要在实际生产代码中使用 __defineSetter__ - 它是非标准的,可能会排除许多浏览器的用户。 标准等效项是defineProperty 对吗?仍然存在引用隐藏属性的问题... 不,它仍然不是一个真正的标准。您不应该使用它,因为它不包括旧浏览器。当然,如果您正在做一些非关键的事情并且它会优雅地降级,那没关系。但它看起来不像你的情况。 在形式上它似乎是一个标准(ecmascript 5),但是是的,我同意它还没有很好的兼容性。别担心,我不会开发任何你最喜欢的网络应用程序:D 前景不太好。见***.com/questions/2920180/… 【参考方案1】:

您只需要一个单独的数据存储属性来存储实际值,就像其他使用 getter 和 setter 的语言一样。您可以使用闭包将它们隐藏起来。

var _innerHTML = "";

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

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

但是,我发现在现有 DOM 属性上使用 getter 和 setter 通常根本不起作用,因为内部对这些属性进行了特殊处理。例如,它不适用于文本 inputvalue 属性。我希望innerHTML 在同一条船上。

【讨论】:

以上是关于在 JavaScript 中访问被 __defineGetter__/__defineSetter__ 隐藏的属性的主要内容,如果未能解决你的问题,请参考以下文章

PHP 判断终端是手机还是电脑访问网站代码

#ifndef #define

oc-03-OC访问OC源文件C源文件中的函数

C进阶详解预处理指令

C++ 实现日志系统

PHP类与面向对象