14

It is the predominant opinion that built-in Javascript prototypes should not be extended (or altered in any way):

Array.prototype.empty = function () { return this.length === 0; } // don't try that

Does this rule also apply to ES2015 symbols?

const empty = Symbol("empty");
Array.prototype[empty] = function empty() { return this.length === 0; }

Since symbol is a mix of string (primitive, immutable) and object (identity) there can be no object property naming conflicts by definition.

Normal object reflection is not affected by symbols:

Object.getOwnPropertyNames(Array.prototype).indexOf("empty"); // -1

But ES2015 reflection with Reflect.ownKeys(Array.prototype) is.

So this question is mainly about how we'll use Reflect.ownKeys and Object.getOwnPropertySymbols in the future.

Community
  • 1
  • 1
  • 1
    Don't forget you can subclass built-ins now, so there's one more reason not to extend the prototypes of built-ins – CodingIntrigue Jan 13 '16 at 08:22
  • 1
    @RGraham The main reason why I have asked this question is to get a better understanding of use cases or edge cases of symbols, since they are a relatively new feature. I think I won't actually extend built-ins' prototypes. –  Jan 13 '16 at 09:47

1 Answers1

2

Yes.

There are two parts to the "don't modify something you don't own" rule:

  1. You can cause name collisions and you can break their code.

    By touching something you don't own, you may accidentally overwrite something used by some other library. This will break their code in unexpected ways.

  2. You can create tight dependencies and they can break your code.

    By binding your code so tightly to some other object, if they make some significant change (like removing or renaming the class, for example), your code might suddenly break.

Using symbols will avoid #1, but you still run into #2. Tight dependencies between classes like that are generally discouraged. If the other class is ever frozen, your code will still break. The answers on this question still apply, just for slightly different reasons.

You want to focus on loosely binding your dependencies to support better testing (loose bindings are easier to mock) and easier maintenance (a few obvious connections are easier to document and update).

To be clear: the name collisions are just a symptom of the problems caused by tightly-bound dependencies.

Community
  • 1
  • 1
ssube
  • 47,010
  • 7
  • 103
  • 140
  • @IvenMarquardt ES6 or classic prototypes, the impact is the same. You're creating a two-way dependency on something without a contract. Using `String.prototype.substr` is a safe, one-way dependency: you use the function, they provide a contract stating it will exist and how it will behave. Injecting something into `String.prototype` is more round-about (you both modify and use them) and they typically don't provide a contract saying that will remain possible. – ssube Jan 12 '16 at 17:37
  • In the end, this boils down to "that could be dangerous, don't touch it." While that will make real life boring, it makes code *stable*. – ssube Jan 12 '16 at 17:39
  • But if you create an instance of Array.prototype and then make it immutable (freeze), `push` and `pop` etc. are broken too. Can you give another specific example? –  Jan 12 '16 at 17:45
  • @IvenMarquardt Not freezing the instance, freezing the class. They can also remove a class, rename it, require it be imported, or anything else that changes the visibility. Any unexpected changes have the potential to break your code. – ssube Jan 12 '16 at 18:44
  • While I take your examples for too general and unlikely (at least in the context of Javascript), I see your point. Thanks! –  Jan 12 '16 at 19:19
  • @IvenMarquardt it's not a very good example, but I'm drawing a blank on anything else. :( If you find something better, by all means suggest an answer edit! – ssube Jan 12 '16 at 19:32
  • IMO, this answer is not answering the question. For #2, upgrading any basic APIs will break any code. This is in principle that no one can avoid. Since this is unanswered,I created Q https://stackoverflow.com/questions/71505938/is-object-freezeobject-prototype-only-the-hazard-for-extending-object-proto. – sailsky Mar 17 '22 at 01:34