回答編集履歴
4
「型の判定」節を追記
answer
CHANGED
@@ -265,6 +265,38 @@
|
|
265
265
|
</script>
|
266
266
|
```
|
267
267
|
|
268
|
+
### 型の判定
|
269
|
+
|
270
|
+
Object 型を期待する変数は Object 型もしくは Null 型を代入すべき変数です。
|
271
|
+
|
272
|
+
```HTML
|
273
|
+
<script>
|
274
|
+
var a = 1;
|
275
|
+
</script>
|
276
|
+
<script>
|
277
|
+
var a = a || {};
|
278
|
+
console.log(a); // 1
|
279
|
+
</script>
|
280
|
+
```
|
281
|
+
|
282
|
+
期待に反して、変数 `a` には Number 型の値が代入されています。
|
283
|
+
この状況は、次のコードで改善されます。
|
284
|
+
|
285
|
+
```HTML
|
286
|
+
<script>
|
287
|
+
var a = 1;
|
288
|
+
</script>
|
289
|
+
<script>
|
290
|
+
if (Object(a) !== a) {
|
291
|
+
throw new TypeError(a + ' is not a object'); // TypeError: 1 is not a object
|
292
|
+
}
|
293
|
+
var a = {};
|
294
|
+
console.log(a);
|
295
|
+
</script>
|
296
|
+
```
|
297
|
+
|
298
|
+
`TypeError` を発生させる事で Object 型以外の値が代入されている事が分かります。
|
299
|
+
|
268
300
|
### まとめ
|
269
301
|
|
270
302
|
まとめると、次のようになると思います。
|
@@ -278,9 +310,13 @@
|
|
278
310
|
- [Internet Explorer のサポートポリシーが変わります - MSBC](https://www.microsoft.com/japan/msbc/Express/ie_support/)
|
279
311
|
- [Windows Vista のサポートは終了しました - Windows Help](https://support.microsoft.com/ja-jp/help/22882/windows-vista-end-of-support)
|
280
312
|
|
313
|
+
ただし、「型の判定」節で触れている通り、`var a = a || {};` は Object 型以外の値が代入するケースを排除できない問題があります。
|
314
|
+
判定条件が緩い為、`Object()` で正しく判定するコードがより好ましいといえます。
|
315
|
+
|
281
316
|
### 更新履歴
|
282
317
|
|
283
318
|
- 2017/08/05 00:58 「Object.defineProperty() と const」を追記
|
284
319
|
- 2017/08/09 10:56 const による再代入禁止のコード事例が再定義禁止になっていた為、再代入禁止のコードに修正
|
320
|
+
- 2017/08/09 11:51 「型の判定」節を追記
|
285
321
|
|
286
322
|
Re: LanHma さん
|
3
const による再代入禁止のコード事例が再定義禁止になっていた為、再代入禁止のコードに修正
answer
CHANGED
@@ -240,13 +240,31 @@
|
|
240
240
|
</script>
|
241
241
|
<script>
|
242
242
|
'use strict';
|
243
|
-
|
243
|
+
a = {bar: 2}; // TypeError: Assignment to constant variable. (再代入禁止)
|
244
244
|
</script>
|
245
|
+
<script>
|
246
|
+
'use strict';
|
247
|
+
var a = {bar: 2}; // SyntaxError: Identifier 'a' has already been declared (再定義禁止)
|
248
|
+
</script>
|
245
249
|
```
|
246
250
|
|
251
|
+
`TypeError` が `const` による再代入禁止、`SyntaxError` は再定義禁止による規定によるものです。
|
247
|
-
|
252
|
+
`let` も再定義禁止の為、`var`, `let`, `const` による同じ名前の変数宣言を防ぐ事が可能です。
|
248
253
|
|
254
|
+
なお、`const` は再代入は禁止されていますが、プロパティの書き換えは許容されている為、複数のスクリプト間で同じオブジェクトを共有する事は出来ます。
|
249
255
|
|
256
|
+
```HTML
|
257
|
+
<script>
|
258
|
+
'use strict';
|
259
|
+
const a = {foo: 1};
|
260
|
+
</script>
|
261
|
+
<script>
|
262
|
+
'use strict';
|
263
|
+
a.bar = 2; // プロパティの書き換えは出来る
|
264
|
+
console.log(a); // {foo: 1, bar: 2}
|
265
|
+
</script>
|
266
|
+
```
|
267
|
+
|
250
268
|
### まとめ
|
251
269
|
|
252
270
|
まとめると、次のようになると思います。
|
@@ -263,5 +281,6 @@
|
|
263
281
|
### 更新履歴
|
264
282
|
|
265
283
|
- 2017/08/05 00:58 「Object.defineProperty() と const」を追記
|
284
|
+
- 2017/08/09 10:56 const による再代入禁止のコード事例が再定義禁止になっていた為、再代入禁止のコードに修正
|
266
285
|
|
267
286
|
Re: LanHma さん
|
2
「Object\.defineProperty\(\) と const」を追記
answer
CHANGED
@@ -205,17 +205,63 @@
|
|
205
205
|
</script>
|
206
206
|
```
|
207
207
|
|
208
|
+
### Object.defineProperty() と const
|
209
|
+
|
210
|
+
ES3 への配慮が不要なら、グローバル名前空間の衝突対策として、次の2つが有力な選択肢となります。
|
211
|
+
|
212
|
+
- ES5 実装が対象なら、`Object.defineProperty()` を使う
|
213
|
+
- ES6 実装が対象なら、`let` または `const` を使う
|
214
|
+
|
215
|
+
`Object.defineProperty()` の有効性は説明済みなので省くとして、ES6 では特に `const` が衝突検出器として有力です。
|
216
|
+
`Object.defineProperty()` による上書き禁止のコードでは上書きはできないものの、上書きを試みたタイミングでは何も発生しない静かなコードでした。
|
217
|
+
|
218
|
+
```HTML
|
219
|
+
<script>
|
220
|
+
Object.defineProperty(this, 'a', {
|
221
|
+
writable: false, // 上書き禁止
|
222
|
+
enumerable: false,
|
223
|
+
configurable: true,
|
224
|
+
value: {foo: 1}
|
225
|
+
});
|
226
|
+
</script>
|
227
|
+
<script>
|
228
|
+
var a = {bar: 2, piyo: function () { return this.bar; }}; // 上書き禁止だが、ここではエラーが発生しない
|
229
|
+
console.log(a.bar); // undefined (ここでもエラーが発生しない)
|
230
|
+
console.log(a.piyo()); // TypeError: a.piyo is not a function
|
231
|
+
</script>
|
232
|
+
```
|
233
|
+
|
234
|
+
`const` は**再代入を禁止する**為、上書きする事が出来ません。
|
235
|
+
|
236
|
+
```HTML
|
237
|
+
<script>
|
238
|
+
'use strict';
|
239
|
+
const a = {foo: 1};
|
240
|
+
</script>
|
241
|
+
<script>
|
242
|
+
'use strict';
|
243
|
+
var a = {bar: 2}; // SyntaxError: Identifier 'a' has already been declared
|
244
|
+
</script>
|
245
|
+
```
|
246
|
+
|
247
|
+
なお、`const` は再代入は禁止されていますが、プロパティの書き換えは許容されている為、複数のスクリプト間で同じオブジェクトを共有する事は可能です。
|
248
|
+
|
249
|
+
|
208
250
|
### まとめ
|
209
251
|
|
210
|
-
|
252
|
+
まとめると、次のようになると思います。
|
211
253
|
|
212
|
-
- ES3 実装に対応する必要があり、Polyfill を書く場合
|
213
|
-
- ES3 実装
|
254
|
+
- ES3 実装が対象なら、Polyfill もしくは複数の自作ライブラリ間でオブジェクトを共有する場合に `var` 宣言を使う
|
255
|
+
- ES5 実装が対象なら、`Object.defineProperty()` を使う
|
256
|
+
- ES6 実装が対象なら、`let` または `const` を使う
|
214
257
|
|
215
258
|
最も、Microsoft は2017/04/11(Windows Vista のサポート終了日)に IE10- のサポートを終了している為、ES3 に配慮する場面は少ないと思います。
|
216
259
|
|
217
|
-
|
218
260
|
- [Internet Explorer のサポートポリシーが変わります - MSBC](https://www.microsoft.com/japan/msbc/Express/ie_support/)
|
219
261
|
- [Windows Vista のサポートは終了しました - Windows Help](https://support.microsoft.com/ja-jp/help/22882/windows-vista-end-of-support)
|
220
262
|
|
263
|
+
### 更新履歴
|
264
|
+
|
265
|
+
- 2017/08/05 00:58 「Object.defineProperty() と const」を追記
|
266
|
+
|
221
267
|
Re: LanHma さん
|
1
2017/04/11\(Windows Vista のサポート終了日\)
answer
CHANGED
@@ -212,6 +212,10 @@
|
|
212
212
|
- ES3 実装に対応する必要があり、Polyfill を書く場合
|
213
213
|
- ES3 実装に対応する必要があり、複数の自作ライブラリ間でオブジェクトを共有する場合
|
214
214
|
|
215
|
-
最も、
|
215
|
+
最も、Microsoft は2017/04/11(Windows Vista のサポート終了日)に IE10- のサポートを終了している為、ES3 に配慮する場面は少ないと思います。
|
216
216
|
|
217
|
+
|
218
|
+
- [Internet Explorer のサポートポリシーが変わります - MSBC](https://www.microsoft.com/japan/msbc/Express/ie_support/)
|
219
|
+
- [Windows Vista のサポートは終了しました - Windows Help](https://support.microsoft.com/ja-jp/help/22882/windows-vista-end-of-support)
|
220
|
+
|
217
221
|
Re: LanHma さん
|