JavaScript: Extending Element prototype

☆樱花仙子☆ 提交于 2019-12-05 04:55:25

Is it ok? Technically yes. Should you extend native APIs? As a rule of thumb no. Unfortunately the answer is more complex. If you are writing a large framework like Ember or Angular it may be a good idea to do so because your consumers will have Benifits if better API convenience. But if you're only doing this for yourself then the rule of thumb is no.

The reasoning is that doing so destabilizes the trust of that object. In other words by adding, changing, modifying a native object it no longer follows the well understood and documented behavior that anyone else (including your future self) will expect.

This style hides implementation that can go unnoticed. What is this new method?, Is it a secret browser thing?, what does it do?, Found a bug do I report this to Google or Microsoft now?. A bit exaggerated but the point is that the truth of an API has now changed and it is unexpected in this one off case. It makes maintainability need extra thought and understanding that would not be so if you just used your own function or wrapper object. It also makes changes harder.

Relevant post: Extending builtin natives. Evil or not?

Instead of trying to muck someone else's (or standard) code just use your own.

function toggleAttribute(el, attribute, value) {
  var _value = (value == null ? true : value;
  if (el.hasAttribute(attribute)) {
    el.removeAttribute(attribute);
  } else {
    el.addAttribute(attribute, _value);
  }
};

Now it is safe, composible, portable, and maintainable. Plus other developers (including your future self) won't scratch their heads confused where this magical method that is not documented in any standard or JS API came from.

Do not modify objects you don't own.

Imagine a future standard defines Element.prototype.toggleAttribute. Your code checks if it has a truthy value before assigning your function. So you could end up with the future native function, which may behave differently than what you expected.

Even more, just reading Element.prototype.toggleAttribute might call a getter, which could run some code with undesired sideways effects. For example, see what happens when you get Element.prototype.id.

You could skip the check and assign your function directly. But that could run a setter, with some undesired sideways effects, and your function wouldn't be assigned as the property.

You could use a property definition instead of a property assignment. That should be safer... unless Element.prototype has some special [[DefineOwnProperty]] internal method (e.g. is a proxy).

It might fail in lots of ways. Don't do this.

In my assessment: no

Massive overwriting Element.prototype slow down performance and can conflict with standardization, but a technical reason does not exist.

I'm using several Element.prototype custom methods. so far so good until I observe a weird behaviour.

<!DOCTYPE html >
<html >
<body>
<script>
function doThis( ){
    alert('window');
}
HTMLElement.prototype.doThis = function(  ){
    alert('HTMLElement.prototype');
}
</script>
<button onclick="doThis( )" >Do this</button>
</body>
</html>

when button is clicked, the prototype method is executed instead of the global one. The browser seems to assume this.doThis() which is weird. To overcome, I have to use window.doThis() in the onclick.

It might be better if w3c can come with with diff syntax for calling native/custom methods e.g.

myElem.toggleAttribute() // call native method
myElem->toggleAttribute() // call custom method

Is there any technical reason not to extend the Element prototype.

Absolutely none!

pardon me: ABSOLUTELY NONE!

In addition the .__proto__, was practically an a illegal prototype extension until yesterday. - Today, it's a Standard.


p.s.: You should avoid the use of if(!Element.prototype.toggleAttribute) syntax by any means, the if("toggleAttribute" in Element.prototype) will do.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!