javascript - 为什么我不能为 Object.prototype.click 分配一个函数?

标签 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 属性。

但是,代码运行起来,却没有触发点击事件,也没有报错。

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被保留了?如果是这样,为什么我不能覆盖它的定义?

我做错了什么?

最佳答案

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

另一个问题是btn1是一个元素,而不仅仅是一个对象,HTMLElement有一个click 原型(prototype)上的属性。因此,即使您分配给 Object.prototype.clickHTMLElement.prototype.click 也会更快地出现在原型(prototype)链中,因此您的 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 属性直接分配给实例,而不是分配给原型(prototype):

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>

关于javascript - 为什么我不能为 Object.prototype.click 分配一个函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53902365/

相关文章:

Javascript 类重写方法

javascript - 其他浏览器中类似 WebKit 的磨砂玻璃

javascript - Node.js 解析 JSON

javascript - 直接在 JS 中动态改变 transition 还是使用 css classes 对性能更好?

javascript - Node.js:从 JSON 响应中提取数据

javascript - 如何使视差滚动到多列

javascript - CKEditor 在选择标签上添加样式

javascript - YUI dataTable 行可展开/可折叠

javascript - 当对象跟随鼠标时,为什么 JavaScript 中存在滞后?

javascript - react 状态扩展多级对象不起作用