为什么不能将函数分配给Object.prototype.click?

时间:2018-12-23 08:55:36

标签: javascript

我知道如何创建动态元素并将其添加到现有元素,以及如何创建点击事件并将其附加。请在下面查看我的代码段

var container = document.getElementById("container");

var btn1 = document.createElement("button");
var btn2 = document.createElement("button");

btn1.innerHTML = "button 1";
btn2.innerHTML = "button 2";

btn1.onclick = function(){ console.log('button 1 clicked'); };   // this works fine
btn2.onclick = function(){ console.log('button 2 clicked'); };   

container.append(btn1);
container.append(btn2);
<div id="container"></div>

我正在尝试模仿jQuery的.click()行为。 (我不想使用jQuery,我只需要一种将点击事件分配给动态创建的元素的较短方法。)

我的意思是,我想通过添加一个接受函数作为参数的函数来扩展Object.prototype,并且它在幕后所做的全部工作就是将其分配给对象的.onclick属性。

但是,代码会运行,但是不会触发click事件,并且不会报告任何错误。

var container = document.getElementById("container");

var btn1 = document.createElement("button");
var btn2 = document.createElement("button");

btn1.click(function(){ console.log('button 1 clicked'); });  // this doesn't work
btn2.click(function(){ console.log('button 2 clicked'); });  // this doesn't work

btn1.innerHTML = "button 1";
btn2.innerHTML = "button 2";

container.append(btn1);
container.append(btn2);

Object.prototype.click = function(fn) {
   console.log('this function never gets executed');
   this.onclick = fn;
}
<div id="container"></div>

我可以说我的Object.prototype.click扩展名从未执行过,因为console.log()从未发生。

是因为Object.prototype.click被保留了吗?如果是这样,为什么我不能覆盖其定义?

我在做什么错了?

1 个答案:

答案 0 :(得分:12)

有两个问题。首先,应在尝试调用btn1.click()之前将 分配给原型,否则将调用 native .click()。 (元素的本机.click()方法以编程方式触发该元素的click事件。)

另一个问题是btn1是一个元素,而不仅仅是一个对象,并且HTMLElement的原型具有click属性。因此,即使您分配给Object.prototype.click,也将在原型链中更快地看到HTMLElement.prototype.click,因此您的Object.prototype.click将被忽略。您将不得不覆盖HTMLElement.prototype.clickHTMLButtonElement.click

var container = document.getElementById("container");

var btn1 = document.createElement("button");
var btn2 = document.createElement("button");

HTMLElement.prototype.click = function(fn) {
   console.log('setting up click event');
   this.onclick = fn;
}

btn1.click(function(){ console.log('button 1 clicked'); });
btn2.click(function(){ console.log('button 2 clicked'); });

btn1.innerHTML = "button 1";
btn2.innerHTML = "button 2";

container.append(btn1);
container.append(btn2);
<div id="container"></div>

但是像这样对内置对象进行突变并不是很好的做法,并且可能导致事情中断(例如,如果库假设.click()将触发常规的HTMLElement.prototype.click函数)-您可以考虑直接将click属性分配给实例,而不是原型:

var container = document.getElementById("container");

function myCreateElement(type) {
  const elm = document.createElement(type);
  elm.click = function(fn) {
    console.log('setting up click event');
    this.onclick = fn;
  }
  return elm;
}

var btn1 = myCreateElement("button");
var btn2 = myCreateElement("button");

btn1.click(function(){ console.log('button 1 clicked'); });
btn2.click(function(){ console.log('button 2 clicked'); });

btn1.innerHTML = "button 1";
btn2.innerHTML = "button 2";

container.append(btn1);
container.append(btn2);
<div id="container"></div>