我们可以覆盖Javascript DOM对象原型属性吗?

时间:2015-12-19 23:21:52

标签: javascript html dom ecmascript-6 ecmascript-5

我一直在寻找一种方法来永久更改HTMLFormElement Javascript对象的'onsubmit'行为。我们假设我的一个Javascript将包含以下代码:

HTMLFormElement.prototype.onsubmit = function () {
    this.submit();
    // Make sure that you can only submit once.
    this.onsubmit = function () {
        return false;
    };
    return false;
};

这个想法是简单地防止在所有形式的文件上提交双重提交。由于上面的例子不起作用,我无法弄清楚如何做到这一点。

有没有办法在文档加载后没有循环遍历所有现有的HTMLElements来实现这一点?一种与某些旧版浏览器兼容的方法,如果使用其他脚本创建新的表单元素,也会保留该行为。 (仅限香草JS)

3 个答案:

答案 0 :(得分:0)

这个怎么样?

[].forEach.call(document.getElementsByTagName('form'), function(form) {
  form.onsubmit = function () {
    // Make sure that you can only submit once.
    this.onsubmit = function () {
      return false;
    };
    return true;
  };
});

答案 1 :(得分:0)

tl;博士:没有,请像@Louy说的那样,这是对的。 DOM被设计为循环使用,不用担心。

是的,您可以覆盖HTMLElement属性,HTMLElement后代也属于同一属性。但特别是对于某些属性,例如事件回调,您不允许这样做,因为它们不是正常属性,而是getterssetters。我的代码出现以下错误,这可能是您的意思" 无法正常工作":

image description

即使你实现了这一点,我也不确定结果行为是否由标准定义。我认为这肯定不会导致浏览器之间存在任何兼容性。

我的经验还表明,全局更改某些API因为您需要它来执行特定功能并不是一个好主意 - 很快您的请求可能会发生变化,您将会更改整个API。

答案 2 :(得分:0)

是的,您可以覆盖JavaScript DOM对象原型属性。但是,你永远不应该......永远都这样做!也就是说,除非您正在编写一个应该添加标准行为的polyfill,以便不支持它的浏览器。除非你处于非常特殊且相当罕见的情况,you're not supposed to ever modify objects you don’t own

对于您的特定用例,除了第一次点击外,每次点击提交按钮时都可以使用event.preventDefault()轻松达到预期效果:

var alreadySubmitted = false;

document.getElementById("submitbutton").addEventListener("click", function(event){
    if(!alreadySubmitted) {
        // The first time the button is clicked
        alreadySubmitted = true;
    } else {
        // All subsequent times the button is clicked
        event.preventDefault();
    }
}, false);