Skip to content

Commit 32a3d17

Browse files
RobbieTheWagnerjenweber
authored andcommitted
Wrap arrays to avoid prototype extensions (ember-learn#691)
* Wrap arrays to avoid prototype extensions Fixes ember-learn#532 * Add note about disabling prototype extensions * Wrap in cta markup * Update CTA
1 parent 8b07190 commit 32a3d17

File tree

5 files changed

+49
-15
lines changed

5 files changed

+49
-15
lines changed

guides/release/applications/services.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,15 @@ Like any Ember object, a service is initialized and can have properties and meth
3333
Below, the shopping cart service manages an items array that represents the items currently in the shopping cart.
3434

3535
```javascript {data-filename=app/services/shopping-cart.js}
36+
import { A } from '@ember/array';
3637
import Service from '@ember/service';
3738

3839
export default Service.extend({
3940
items: null,
4041

4142
init() {
4243
this._super(...arguments);
43-
this.set('items', []);
44+
this.set('items', A([]));
4445
},
4546

4647
add(item) {

guides/release/components/the-component-lifecycle.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,18 @@ you can use `didUpdateAttrs` to clear any error state that was built up from edi
6161
```
6262

6363
```javascript {data-filename=/app/components/profile-editor.js}
64+
import { A } from '@ember/array';
6465
import Component from '@ember/component';
6566

6667
export default Component.extend({
6768
init() {
6869
this._super(...arguments);
69-
this.set('errors', []);
70+
this.set('errors', A([]));
7071
},
7172

7273
didUpdateAttrs() {
7374
this._super(...arguments);
74-
this.set('errors', []);
75+
this.set('errors', A([]));
7576
},
7677

7778
actions: {

guides/release/object-model/classes-and-instances.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,11 @@ setup work, and you'll see strange behavior in your application.
171171
Arrays and objects defined directly on any `Ember.Object` are shared across all instances of that class.
172172

173173
```javascript
174+
import { A } from '@ember/array';
174175
import EmberObject from '@ember/object';
175176

176177
const Person = EmberObject.extend({
177-
shoppingList: ['eggs', 'cheese']
178+
shoppingList: A(['eggs', 'cheese'])
178179
});
179180

180181
Person.create({
@@ -198,11 +199,12 @@ Person.create({
198199
To avoid this behavior, it is encouraged to initialize those arrays and object properties during `init()`. Doing so ensures each instance will be unique.
199200

200201
```javascript
202+
import { A } from '@ember/array';
201203
import EmberObject from '@ember/object';
202204

203205
const Person = EmberObject.extend({
204206
init() {
205-
this.set('shoppingList', ['eggs', 'cheese']);
207+
this.set('shoppingList', A(['eggs', 'cheese']));
206208
}
207209
});
208210

guides/release/object-model/computed-properties-and-aggregate-data.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,19 @@ In those cases we can use the `[]` array key to tell the property to update at t
1010
We'll use the familiar todo list for our examples:
1111

1212
```javascript {data-filename=app/components/todo-list.js}
13+
import { A } from '@ember/array';
1314
import EmberObject, { computed } from '@ember/object';
1415
import Component from '@ember/component';
1516

1617
export default Component.extend({
1718
todos: null,
1819

1920
init() {
20-
this.set('todos', [
21+
this.set('todos', A([
2122
EmberObject.create({ title: 'Buy food', isDone: true }),
2223
EmberObject.create({ title: 'Eat food', isDone: false }),
2324
EmberObject.create({ title: 'Catalog Tomster collection', isDone: true }),
24-
]);
25+
]));
2526
},
2627

2728
titles: computed('todos.[]', function() {
@@ -108,6 +109,7 @@ Ember also provides a computed property macro
108109
which is a shorter way of expressing the above computed property:
109110

110111
```javascript {data-filename=app/components/todo-list.js}
112+
import { A } from '@ember/array';
111113
import EmberObject, { computed } from '@ember/object';
112114
import { filterBy } from '@ember/object/computed';
113115
import Component from '@ember/component';
@@ -116,11 +118,11 @@ export default Component.extend({
116118
todos: null,
117119

118120
init() {
119-
this.set('todos', [
121+
this.set('todos', A([
120122
EmberObject.create({ isDone: true }),
121123
EmberObject.create({ isDone: false }),
122124
EmberObject.create({ isDone: true }),
123-
]);
125+
]));
124126
},
125127

126128
incomplete: filterBy('todos', 'isDone', false)

guides/release/object-model/enumerables.md

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,29 @@ possible. This minimizes incompatibility with other libraries, and
1414
allows Ember.js to use the native browser implementations in arrays
1515
where available.
1616

17+
<div class="cta">
18+
<div class="cta-note">
19+
<div class="cta-note-body">
20+
<div class="cta-note-heading">Zoey says...</div>
21+
<div class="cta-note-message">
22+
It is best practice to
23+
<a href="https://guides.emberjs.com/release/configuring-ember/disabling-prototype-extensions/">
24+
disable prototype extensions
25+
</a>
26+
in your app.
27+
28+
For example, with prototype extensions disabled, Ember's convenience methods like <code>firstObject</code> will only
29+
be available on <code>EmberArray</code>s and will not work on native JavaScript arrays.
30+
This configuration is especially important for apps that use
31+
<a href="https://ember-fastboot.com/">
32+
Ember Fastboot
33+
</a>.
34+
</div>
35+
</div>
36+
<img src="/images/mascots/zoey.png" role="presentation" alt="Ember Mascot">
37+
</div>
38+
</div>
39+
1740
## Use of Observable Methods and Properties
1841

1942
In order for Ember to observe when you make a change to an enumerable, you need
@@ -74,7 +97,9 @@ that you can bind to.
7497

7598

7699
```javascript
77-
let animals = ['rooster', 'pig'];
100+
import { A } from '@ember/array';
101+
102+
let animals = A(['rooster', 'pig']);
78103

79104
animals.get('lastObject');
80105
//=> "pig"
@@ -105,6 +130,7 @@ in turn and return a new array:
105130

106131

107132
```javascript
133+
import { A } from '@ember/array';
108134
import EmberObject from '@ember/object';
109135

110136
let hawaii = EmberObject.create({
@@ -115,7 +141,7 @@ let california = EmberObject.create({
115141
capital: 'Sacramento'
116142
});
117143

118-
let states = [hawaii, california];
144+
let states = A([hawaii, california]);
119145

120146
states.mapBy('capital');
121147
//=> ["Honolulu", "Sacramento"]
@@ -144,17 +170,18 @@ When working with a collection of Ember objects, you will often want to filter a
144170

145171

146172
```javascript
173+
import { A } from '@ember/array';
147174
import EmberObject from '@ember/object';
148175

149176
Todo = EmberObject.extend({
150177
title: null,
151178
isDone: false
152179
});
153180

154-
let todos = [
181+
let todos = A([
155182
Todo.create({ title: 'Write code', isDone: true }),
156183
Todo.create({ title: 'Go to sleep' })
157-
];
184+
]);
158185

159186
todos.filterBy('isDone', true);
160187

@@ -173,17 +200,18 @@ use the [`every()`](https://emberjs.com/api/ember/release/classes/MutableArray/m
173200

174201

175202
```javascript
203+
import { A } from '@ember/array';
176204
import EmberObject from '@ember/object';
177205

178206
Person = EmberObject.extend({
179207
name: null,
180208
isHappy: false
181209
});
182210

183-
let people = [
211+
let people = A([
184212
Person.create({ name: 'Yehuda', isHappy: true }),
185213
Person.create({ name: 'Majd', isHappy: false })
186-
];
214+
]);
187215

188216
people.every((person, index, self) => person.get('isHappy'));
189217

0 commit comments

Comments
 (0)