Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript: Extending Element prototype

I have seen a lot of discussion regarding extending Element. As far as I can tell, these are the main issues:

  • It may conflict with other libraries,
  • It adds undocumented features to DOM routines,
  • It doesn’t work with legacy IE, and
  • It may conflict with future changes.

Given a project which references no other libraries, documents changes, and doesn’t give a damn for historical browsers:

Is there any technical reason not to extend the Element prototype. Here is an example of how this is useful:

Element.prototype.toggleAttribute=function(attribute,value) {
    if(value===undefined) value=true;
    if(this.hasAttribute(attribute)) this.removeAttribute(attribute);
    else this.addAttribute(attribute,value);
};

I’ve seen too many comments about the evils of extending prototypes without offering a reasonable explanation.

Note 1: The above example is possibly too obvious, as toggleAttribute is the sort of method which might be added in the future. For discussion, imagine that it’s called manngoToggleAttribute.

Note 2: I have removed a test for whether the method already exists. Even if such a method already exists, it is more predictable to override it. In any case, I am assuming that the point here is that the method has not yet been defined, let alone implemented. That is the point here.

Note 3: I see that there is now a standard method called toggleAttribute which doesn’t behave exactly the same. With modification, the above would be a simple polyfill. This doesn’t change the point of the question.

like image 322
Manngo Avatar asked Jul 15 '16 01:07

Manngo


1 Answers

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.

like image 107
Sukima Avatar answered Oct 12 '22 04:10

Sukima