teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

4

「型の判定」節を追記

2017/08/09 02:51

投稿

think49
think49

スコア18194

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 による再代入禁止のコード事例が再定義禁止になっていた為、再代入禁止のコードに修正

2017/08/09 02:51

投稿

think49
think49

スコア18194

answer CHANGED
@@ -240,13 +240,31 @@
240
240
  </script>
241
241
  <script>
242
242
  'use strict';
243
- var a = {bar: 2}; // SyntaxError: Identifier 'a' has already been declared
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
- なお、`const` 代入は禁止されていますが、プロパティ書き換えは許容されている為、複数のスクリプト間で同じオブジェクト共有する可能です。
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」を追記

2017/08/09 01:56

投稿

think49
think49

スコア18194

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
- `var` 宣言を使ったコードを次の2つのケースで有効だと思います。
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 のサポート終了日\)

2017/08/04 15:58

投稿

think49
think49

スコア18194

answer CHANGED
@@ -212,6 +212,10 @@
212
212
  - ES3 実装に対応する必要があり、Polyfill を書く場合
213
213
  - ES3 実装に対応する必要があり、複数の自作ライブラリ間でオブジェクトを共有する場合
214
214
 
215
- 最も、MS IE10- のサポートを打ち切った今では、ES3 に配慮する場面は少ないと思います。
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 さん