You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
4. Keep PR simple and focused - one PR per feature.
9
9
5. Make a Pull Request.
10
10
6. Complete the [Contributor License Agreement](https://docs.google.com/a/playcanvas.com/forms/d/1Ih69zQfJG-QDLIEpHr6CsaAs6fPORNOVnMv5nuo0cjk/viewform).
11
-
7. Happy Days! :)
11
+
7. Happy Days! 🎉
12
12
13
13
#### Tips
14
14
@@ -22,7 +22,7 @@ Try to keep PR focused on a single feature, small PR's are easier to review and
22
22
23
23
## General
24
24
25
-
These coding standards are based on the [Google JavaScript Coding Standards](https://google.github.io/styleguide/javascriptguide.xml). If something is not defined here, use this guide as a backup.
25
+
Our coding standards are derived from the [Google JavaScript Coding Standards](https://google.github.io/styleguide/javascriptguide.xml) which are based on ES5 (ECMA2009). Also we have a whitelist of modern JavaScript features (ES6+), explicitly listed below.
26
26
27
27
### Keep it simple
28
28
@@ -32,6 +32,14 @@ Simple code is always better. Modular (horizontal dependencies) code is easier t
32
32
33
33
For example, use "Initialize" instead of "Initialise", and "color" instead of "colour".
34
34
35
+
### Whitelisted ES6+ features:
36
+
37
+
*`let`, `const` instead of `var`
38
+
*`for of` loop
39
+
*`class` instead of `prototype`
40
+
*`import`/`export` handled by build scripts for bundling
41
+
* function default parameters
42
+
35
43
### Opening braces should be on the same line as the statement
36
44
37
45
For example:
@@ -68,16 +76,16 @@ On save, set your text editor to remove trailing spaces and ensure there is an e
68
76
### Use spaces between operators
69
77
70
78
```javascript
71
-
var foo =16+32/4;
79
+
let foo =16+32/4;
72
80
73
-
for (var i =0, len =list.length; i <len; i++) {
81
+
for (let i =0; i <list.length; i++) {
74
82
// ...
75
83
}
76
84
```
77
85
78
86
### Leave a space after the function keyword for anonymous functions
79
87
```javascript
80
-
varfn=function () {
88
+
letfn=function () {
81
89
82
90
};
83
91
```
@@ -88,59 +96,42 @@ foo();
88
96
bar(1, 2);
89
97
```
90
98
91
-
### Use spaces between [] and { } brackets
99
+
### Use spaces between [] and { } brackets, unless they are empty
92
100
```javascript
93
-
var a = {};
94
-
var b = { key:'value' };
95
-
var c = [];
96
-
var d = [ 32, 64 ];
101
+
let a = {};
102
+
let b = { key:'value' };
103
+
let c = [];
104
+
let d = [ 32, 64 ];
97
105
```
98
106
99
-
### No semicolon on closing function brace
107
+
### `let` and `const` instead of `var` (ES6)
100
108
101
-
Semicolons are not needed to delimit the ends of functions. Follow the convention below:
102
109
```javascript
103
-
functionclass() {
104
-
} // Note the lack of semicolon here
105
-
```
110
+
for (let i =0; i <items.length; i++) {
111
+
constitem= items[i];
112
+
}
106
113
107
-
Semicolons **are** needed if you're function is declared as a variable
108
-
```javascript
109
-
varfn=function () {
110
-
}; // Note the semicolon here
114
+
var a =10; // not good
111
115
```
112
116
113
-
### Put all variable declarations at the top of functions
114
-
115
-
Variable declarations should all be placed first or close to the top of functions. This is because variables have a function-level scope.
116
-
117
-
Variables should be declared one per line.
118
-
117
+
### For of loop (ES6)
119
118
```javascript
120
-
functionfn() {
121
-
var a =0;
122
-
var b =1;
123
-
var c =2;
119
+
// ok
120
+
for (let i =0; i <items.length; i++) {
121
+
constitem= items[i];
124
122
}
125
-
```
126
-
```javascript
127
-
functionfn() {
128
-
var i;
129
-
var bar =0;
130
123
131
-
for(i =0; i <32; ++i) {
132
-
bar += i;
133
-
}
124
+
// more readable but generally slower
125
+
for (constitemof items) {
134
126
135
-
for(var i =0; i <32; i++) { } // don't do this, as i is already defined
136
127
}
137
128
```
138
129
139
130
### Exit logic early
140
131
141
132
In functions exit early to simplify logic flow and avoid building indention-hell:
142
133
```javascript
143
-
varfoo=function (bar) {
134
+
letfoo=function (bar) {
144
135
if (! bar)
145
136
return;
146
137
@@ -150,7 +141,7 @@ var foo = function (bar) {
150
141
151
142
Same for iterators:
152
143
```javascript
153
-
for(var i =0; i <items.length; i++) {
144
+
for (let i =0; i <items.length; i++) {
154
145
if (! items[i].test)
155
146
continue;
156
147
@@ -164,36 +155,36 @@ for(var i = 0; i < items.length; i++) {
164
155
165
156
```javascript
166
157
// Namespace should have short lowercase names
167
-
var namespace = { };
158
+
let namespace = { };
168
159
169
-
// Classes (or rather Constructors) should be CamelCase
170
-
varMyClass=function () { };
160
+
// Classes should be CamelCase
161
+
classMyClass { }
171
162
172
163
// Variables should be mixedCase
173
-
var mixedCase =1;
164
+
let mixedCase =1;
174
165
175
166
// Function are usually variables so should be mixedCase
176
167
// (unless they are class constructors)
177
-
varmyFunction=function () { };
168
+
letmyFunction=function () { };
178
169
179
170
// Constants should be ALL_CAPITALS separated by underscores.
180
171
// Note, ES5 doesn't support constants,
181
172
// so this is just convention.
182
-
varTHIS_IS_CONSTANT="well, kind of";
173
+
constTHIS_IS_CONSTANT="well, kind of";
183
174
184
175
// Private variables should start with a leading underscore.
185
176
// Note, you should attempt to make private variables actually private using
186
177
// a closure.
187
-
var _private ="private";
188
-
var_privateFn=function () { };
178
+
let _private ="private";
179
+
let_privateFn=function () { };
189
180
```
190
181
191
182
### Acronyms should not be upper-case, they should follow coding standards
192
183
193
184
Treat acronyms like a normal word. e.g.
194
185
```javascript
195
-
var json =""; // not "JSON";
196
-
var id =1; // not "ID";
186
+
let json =""; // not "JSON";
187
+
let id =1; // not "ID";
197
188
198
189
functiongetId() { }; // not "getID"
199
190
functionloadJson() { }; // not "loadJSON"
@@ -223,7 +214,7 @@ function asyncFunction(callback) {
223
214
It is often useful to be able to cache the 'this' object to get around the scoping behavior of JavaScript. If you need to do this, cache it in a variable called 'self'.
224
215
225
216
```javascript
226
-
varself=this;
217
+
letself=this;
227
218
```
228
219
229
220
### Avoid using function.bind(scope)
@@ -236,26 +227,47 @@ setTimeout(function() {
236
227
237
228
Instead use `self` reference in upper scope:
238
229
```javascript
239
-
varself=this;
230
+
letself=this;
240
231
setTimeout(function() {
241
232
self.foo();
242
233
});
243
234
```
244
235
236
+
### Default function parameters (ES6)
237
+
238
+
Use this notation for function default parameters:
239
+
```javascript
240
+
// good
241
+
functionfoo(a, b=10) {
242
+
return a + b;
243
+
}
244
+
245
+
// not good
246
+
functionfoo(a, b) {
247
+
if (b ===undefined)
248
+
b =10;
249
+
return a + b;
250
+
}
251
+
```
252
+
253
+
245
254
## Privacy
246
255
247
256
### Make variables private if used only internally
248
257
249
258
Variables that should be accessible only within class should start with `_`:
250
259
```javascript
251
-
varItem=function () {
252
-
this._a="private";
253
-
};
254
-
Item.prototype.bar=function() {
255
-
this._a+="!";
256
-
};
260
+
classItem {
261
+
constructor() {
262
+
this._a="private";
263
+
}
257
264
258
-
var foo =newItem();
265
+
bar() {
266
+
this._a+="!";
267
+
}
268
+
}
269
+
270
+
let foo =newItem();
259
271
foo._a+="?"; // not good
260
272
```
261
273
@@ -264,7 +276,7 @@ foo._a += "?"; // not good
264
276
The hasOwnProperty() function should be used when iterating over an object's members. This is to avoid accidentally picking up unintended members that may have been added to the object's prototype. For example:
265
277
266
278
```javascript
267
-
for (var key in values) {
279
+
for (let key in values) {
268
280
if (!values.hasOwnProperty(key))
269
281
continue;
270
282
@@ -285,51 +297,48 @@ asset-registry.js
285
297
graph-node.js
286
298
```
287
299
288
-
## Namespaces and Classes
300
+
## Namespaces and Classes (ES6)
289
301
290
-
The entire PlayCanvas API must be declared under the ```pc``` namespace. The vast majority of the PlayCanvas codebase is made up of 'class' definitions. These have the following structure (which should be adhered to):
302
+
The entire PlayCanvas API must be declared under the ```pc``` namespace. This is handled by build script, so ES6 notation of `import`/`export` should be used. The vast majority of the PlayCanvas codebase is made up of `class` definitions. These have the following structure (which should be adhered to):
291
303
292
304
```javascript
293
-
Object.assign(pc, function() {
294
-
// Closure to define new class
305
+
classClass {
306
+
someFunc(x) { }
307
+
}
295
308
296
-
varClass=function () {
297
-
};
309
+
export { Class};
310
+
```
298
311
299
-
Object.assign(Class.prototype, {
300
-
someFunc:function () {
312
+
You can also extend existing classes:
301
313
302
-
}
303
-
});
314
+
```javascript
315
+
import { Class } from'./class.js';
316
+
317
+
classSubClassextendsClass {
318
+
constructor() {
319
+
// call parent class constructor
320
+
super();
321
+
}
322
+
323
+
someFunc(x) {
324
+
// if method is overriden
325
+
// this is the way to call parent class method
326
+
super.someFunc(x);
327
+
}
328
+
}
304
329
305
-
return {
306
-
Class: Class
307
-
};
308
-
}());
330
+
export { SubClass };
309
331
```
310
332
311
-
You can also subclass existing classes:
333
+
Use `class` instead of `prototype` for defining Classes:
0 commit comments