[removed] What dangers are in extending Array.prot

2019-01-01 15:15发布

Google JavaScript Style Guide advises against extending the Array.prototype. However, I used Array.prototype.filter = Array.prototype.filter || function(...) {...} as a way to have it (and similar methods) in browsers where they do not exist. MDN actually provides similar example.

I am aware about Object.prototype issues, but Array is not a hash table.

What issues may arise while extending Array.prototype that made Google advise against it?

10条回答
与君花间醉酒
2楼-- · 2019-01-01 15:49

You can easily create somekind of sandbox with poser library.

Take a look on https://github.com/bevacqua/poser

var Array2 = require('poser').Array();
// <- Array

Array2.prototype.eat = function () {
  var r = this[0];
  delete this[0];
  console.log('Y U NO .shift()?');
  return r;
};

var a = new Array2(3, 5, 7);

console.log(Object.keys(Array2.prototype), Object.keys(Array.prototype))
查看更多
唯独是你
3楼-- · 2019-01-01 15:50

Extending the prototype is a trick that only works once. You do and you use a library that also does it (in an incompatible way) and boom!

查看更多
不流泪的眼
4楼-- · 2019-01-01 15:55

I'll give you the bullet points, with key sentences, from Nicholas Zakas' excellent article Maintainable JavaScript: Don’t modify objects you don’t own:

  • Dependability: "The simple explanation is that an enterprise software product needs a consistent and dependable execution environment to be maintainable."
  • Incompatible implementations: "Another peril of modifying objects that you don’t own is the possibility of naming collisions and incompatible implementations."
  • What if everyone did it?: "Simply put: if everyone on your team modified objects that they didn’t own, you’d quickly run into naming collisions, incompatible implementations, and maintenance nightmares."

Basically, don't do it. Even if your project is never going to be used by anyone else, and you're never going to import third party code, don't do it. You'll establish a horrible habit that could be hard to break when you start trying to play nice with others.

查看更多
不再属于我。
5楼-- · 2019-01-01 16:00

As a modern update to Jamund Ferguson's answer:

Usually the advice for not extending Array.prototype or other native prototypes might come down to one of these:

  1. for..in might not work properly
  2. Someone else might also want to extend Array with the same function name
  3. It might not work properly in every browser, even with the shim.

Points 1. and 2. can now be mitigated in ES6 by using a Symbol to add your method.

It makes for a slightly more clumsy call structure, but adds a property that isn't iterated over and can't be easily duplicated.

// Any string works but a namespace may make library code easier to debug. 
var myMethod = Symbol('MyNamespace::myMethod');

Array.prototype[ myMethod ] = function(){ /* ... */ };

var arr = [];

// slightly clumsier call syntax
arr[myMethod]();

// Also works for objects
Object.prototype[ myMethod ] = function(){ /* ... */ };

Pros:

  • For..in works as expected, symbols aren't iterated over.
  • No clash of method names as symbols are local to scope and take effort to retrieve.

Cons:

查看更多
浮光初槿花落
6楼-- · 2019-01-01 16:01

Some people use for ... in loops to iterate through arrays. If you add a method to the prototype, the loop will also try to iterate over that key. Of course, you shouldn't use it for this, but some people do anyway.

查看更多
倾城一夜雪
7楼-- · 2019-01-01 16:03

Prototype does this. It's evil. The following snippet demonstrates how doing so can produce unexpected results:

<script language="javascript" src="https://ajax.googleapis.com/ajax/libs/prototype/1.7.0.0/prototype.js"></script>
<script language="javascript">
  a = ["not", "only", "four", "elements"];
  for (var i in a)
    document.writeln(a[i]);
</script>

The result:

not only four elements function each(iterator, context) { var index = 0; . . .

and about 5000 characters more.

查看更多
登录 后发表回答