使用Javascript的__defineSetter__的奇怪行为

时间:2011-01-07 04:16:54

标签: javascript firefox google-chrome variable-assignment

我有一个大型项目,我需要截取到element.src,element.href,element.style等内容的赋值。我想用 defineSetter 来做这个,但它表现得非常奇怪(使用Chrome 8.0.552.231)

一个例子:

var attribs = ["href", "src", "background", "action", "onblur", "style", "onchange", "onclick", "ondblclick", "onerror", "onfocus", "onkeydown", "onkeypress", "onkeyup", "onmousedown", "onmousemove", "onmouseover", "onmouseup", "onresize", "onselect", "onunload"];
for(a = 0; a < attribs.length; a++) {
  var attrib_name = attribs[a];
  var func = new Function("attrib_value", "this.setAttribute(\"" + attrib_name + "\", attrib_value.toUpperCase());");
  HTMLElement.prototype.__defineSetter__(attrib_name, func);
}

此代码应该做的是在指定attribs中的公共元素属性时,它使用setAttribute()来设置该属性的大写版本。

出于一些非常奇怪的原因,setter仅适用于约1/3的任务。

例如

element.src = "test"

新的src是“TEST”,就像它应该是

然而

element.href = "test"

新的href是“test”,而不是大写

然后即使我尝试element.__lookupSetter__("href"),它也会返回正确的大写设置器

最奇怪的是Chrome和Firefox之间正确拦截了不同的变量

帮助!

2 个答案:

答案 0 :(得分:2)

这不是一个好主意。主机对象(例如DOM元素)不受适用于本机JavaScript对象的通常规则的约束,并且基本上可以执行它们喜欢的操作,并且所有浏览器都或多或少地利用了这一事实。浏览器没有义务为宿主对象提供原型,也没有义务允许您覆盖宿主对象属性的getter和setter,或者尊重任何覆盖默认行为的尝试。

我强烈建议放弃这种方法,而是采用不同的方法,例如为DOM元素编写包装器对象。

更新:包装器方法示例

您可以为DOM元素创建包装器对象,并通过这些包装器执行所有DOM操作。这是许多库(例如YUI)所做的事情。例如:

function ElementWrapper(el) {
    this.domElement = el;
}

ElementWrapper.prototype = {
    // Wrap the DOM methods you need
    appendChild: function(child) {
        this.domElement.appendChild(child);
    },

    // Add custom behaviour, such as converting certain
    // property values to upper case
    setProperty: function(name, value) {
        if (/^(src|href|action)$/i.test(name)) {
            this.domElement[name] = value.toUpperCase();
        } else {
            this.domElement[name] = value;
        }
    }
};

var wrappedEl = new WrappedElement( document.getElementById("foo") );
wrappedEl.setProperty("href", "http://www.google.com/");

答案 1 :(得分:2)

如果你等待WebIDL完全定义DOM的ECMAScript绑定,那么回应Tim Down并加上我自己的两分钱,你将会以更加跨浏览器,符合标准的方式获得更好的运气。在那一点覆盖应该给你精确,明确的行为。但是现在你会变得奇怪。