Skip to content

Commit 698b81f

Browse files
author
James Allardice
committed
Added article on native prototype extension
1 parent f1c94c1 commit 698b81f

File tree

2 files changed

+93
-2
lines changed

2 files changed

+93
-2
lines changed

articles.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ the filename of the new article next to it.
309309
- '{a}' is only available in Mozilla JavaScript extensions (use moz option)
310310
- '{a}' is only available in ES6 (use esnext option)
311311
- `bad-declaration.md` - ~~You might be leaking a variable ({a}) here~~
312-
- Extending prototype of native object
312+
- `extending-native.md` - ~~Extending prototype of native object~~
313313
- `invalid-typeof-value.md` - ~~Invalid typeof value~~
314314
- '{a}' is already defined in outer scope
315315
- A generator function shall contain a yield statement
@@ -365,7 +365,7 @@ the filename of the new article next to it.
365365
- Use '===' to compare with 'null'
366366
- `eval.md` - ~~eval can be harmful~~
367367
- `exception-assignment.md` - ~~Do not assign to the exception parameter~~
368-
- {{a}} prototype is read only, properties should not be added
368+
- `extending-native.md` - ~~{{a}} prototype is read only, properties should not be added~~
369369
- Redundant double negation in {{a}}
370370
- Gratuitous parentheses around expression
371371
- `unnecessary-semicolon.md` - ~~Unnecessary semicolon~~
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<!---
2+
{
3+
"titles": [
4+
"Extending prototype of native object: '{a}'",
5+
"{a} prototype is read only, properties should not be added",
6+
"W121"
7+
],
8+
"slugs": [
9+
"extending-prototype-of-native-object",
10+
"a-prototype-is-read-only",
11+
"w121"
12+
],
13+
"linters": [
14+
"jshint",
15+
"eslint"
16+
],
17+
"author": "jallardice"
18+
}
19+
-->
20+
21+
### When do I get this error?
22+
23+
The "Extending prototype of native object: '{a}'" error, and the alternative
24+
"{a} prototype is read only, properties should not be added" error, is thrown
25+
when JSHint (only versions 2.3.0 and above) or ESLint encounters **a assignment
26+
to a property of the `prototype` of a native object*. JSHint will only raise
27+
this warning if the `freeze` option is set to `true`. The following example
28+
defines a `reverse` method on the native `String` prototype:
29+
30+
<!---
31+
{
32+
"linter": "jshint"
33+
}
34+
-->
35+
```javascript
36+
/*jshint freeze: true */
37+
String.prototype.reverse = function () {
38+
"use strict";
39+
return this.split("").reverse().join("");
40+
};
41+
```
42+
43+
ESLint will also issue the warning when the `Object.defineProperty` method is
44+
used. JSHint does not warn in this situation:
45+
46+
<!---
47+
{
48+
"linter": "eslint"
49+
}
50+
-->
51+
```javascript
52+
/*jshint freeze: true */
53+
Object.defineProperty(String.prototype, "reverse", {
54+
value: function () {
55+
"use strict";
56+
return this.split("").reverse().join("");
57+
}
58+
});
59+
```
60+
61+
*Side note*: the implementation of string reversal above is naive because it
62+
fails to take into account the way characters are encoded internally in
63+
JavaScript. See [this Stack Overflow answer][reverse] for a great explanation.
64+
65+
### Why do I get this error?
66+
67+
This error is raised to highlight the use of a technique commonly regarded as
68+
**bad practice**. By defining custom properties on native prototypes you can
69+
easily introduce problems in old browsers (in particular Internet Explorer 8 and
70+
below). The first pattern shown above will result in an enumerable property on
71+
`String.prototype`. If this is done to `Object.prototype` the new property will
72+
be produced by the `for...in` construct causing unexpected iterations of the
73+
loop.
74+
75+
It's also very easy to accidentally shadow custom native prototype methods. For
76+
example, imagine you have defined a `count` method on `Object.prototype` which
77+
returns the number of properties an object has. If any object defines its own
78+
`count` property as part of the program logic the prototype method will be
79+
shadowed and inaccessible via the normal member operator. This makes it easy to
80+
introduce bugs and can also affect third party code.
81+
82+
In ESLint the rule that generates this warning is named `no-extend-native`. You
83+
can disable it by setting it to `0`, or enable it by setting it to `1`.
84+
85+
In JSHint 1.0.0 and above you have the ability to ignore any warning with a
86+
[special option syntax][jshintopts]. The identifier of this warning is **W121**.
87+
This means you can tell JSHint to not issue this warning with the `/*jshint
88+
-W121 */` directive. You can also set the `freeze` option to `false`.
89+
90+
[reverse]: http://stackoverflow.com/questions/958908/how-do-you-reverse-a-string-in-place-in-javascript/16776621#16776621
91+
[jshintopts]: http://jshint.com/docs/#options

0 commit comments

Comments
 (0)