質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

6回答

1881閲覧

変数に論理演算子を使用する意味を教えて下さい。

LanHma

総合スコア192

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

3クリップ

投稿2017/08/04 08:49

いつもお世話になっております。質問をさせて下さい。
サンプルコードを拝見した際に以下のコードがありました。

javascript

1var e, i, a = a || {}, o = o || {}, r = r || {}, l = "", d = 関数

複数の変数を宣言しているのはなんとなくわかるのですが、下記の部分でご質問があります。

javascript

1var a = a || {}, o = o || {}, r = r || {}

ここでの論理演算子の意味がわかりません。実際に実行してみると

javascript

1console.log(a); 2//実行結果 Object {}

となります。それなら初めから

javascript

1var a = {}

とするのは駄目なのでしょうか?
どうしてこのような書き方をしているのか...
大変お手数ではございますがご教授頂けますと幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答6

0

ベストアンサー

var a = a || {};というコードは避けるべき書き方、または、意味をなさない書き方です。

【注意】
varがないa = a || {}window.a = window.a || {}という書き方や、||の左辺がaではないvar a = window.a || {}という書き方を否定する訳ではありません。

この文章はES5以上を想定しており、ES3は一切考慮していません。ES3についてはthink49さんの回答を参考にしてください。

###varの巻き上げ

JavaScriptではvarの巻き上げという仕様があります。

JavaScript

1// 前に書かれたコード 2var a = a || {}; 3// 後に書かれたコード

こういうコードがあった場合、

JavaScript

1var a; // undefiendが入る 2// 前に書かれたコード 3a = a || {}; 4// 後に書かれたコード

と解釈されます。var宣言された変数は、そのスコープ(トップレベルまたは関数がスコープになります)の先頭で宣言され、かつ、undefinedが代入された見なされます。これはトップレベルでも関数ブロック内でも同様です。これを前提に話をします。

###事前にaがありえるのか?

var a = a || {};の前にaに何らかの値が入る場合の想定として、下記が考えられます。

  1. 単純に代入している。
  2. 関数の引数として使用している。
  3. クロージャーで外側で定義されている。
  4. グローバル変数として定義している。
  5. 他ファイルでグローバル変数として定義している。
  6. 最初からグローバル変数として定義されている。

それぞれ見ていきます。

####1. 単純に代入している。

JavaScript

1a = 1; 2var a = a || {};

は、var巻き上げにより、

JavaScript

1var a; 2a = 1; 3a = a || {};

と同じになります。言ってしまえば、varで宣言していた変数を事前に使っていただけに過ぎません。このJavaScriptの仕様は多くのバグをもたらす要因の一つであり、そのような混乱を避けるべきです。つまり、最初から後者の書き方をすべきであって、後から、var宣言を書くべきではありません。最初からaが宣言されていることが自明であれば、同じaを使用していると理解することが可能になります。

####2. 関数の引数として使用している。

JavaScript

1function f(a) { 2 var a = a || {}; 3 // ... 4}

これはどうでしょうか?var宣言の前にaに代入されているように見えます。

いいえ、これはvar宣言自体が無意味です。なぜなら、関数の引数はvar宣言されたのと同じだからです。つまり、引数は次のように解釈できます。

JavaScript

1funciton f() { 2 var a = arguments[0]; 3 var a = a || {}; 4 // ... 5}

varは何度でも宣言できますが、一回宣言されたとの同じになります。つまり、次のようになります。

JavaScript

1funciton f() { 2 var a; 3 a = arguments[0]; 4 a = a || {}; 5 // ... 6}

つまり、次のように書いてしまえば良いと言うことです。

JavaScript

1funciton f(a) { 2 a = a || {}; 3 // ... 4}

結局var不要です。そして、aはそもそも引数であると言うことがこの方がわかりやすいです。なお、引数のデフォルト値を設定するという意味で使っているのであればさらに意味がありません。なぜなら、JavaScriptではundefined以外にもnullfalse+0-0NaN""も偽だからです。引数が与えられない場合にundefinedになることを利用してデフォルト値を設定するのであれば、次のようにすべきでしょう。

JavaScript

1funciton f(a) { 2 a = (typeof a !== 'undefined') ? a : {}; 3 // ... 4}

ECMAScript2015以降であれば、さらに簡単に書けます。

JavaScript

1funciton f(a = {}) { 2 // ... 3}

####3. クロージャーで外側で定義されている。

期待通りに動きません。

JavaScript

1(funciton(){ 2 var a = 1; 3 function f() { 4 var a = a || {}; 5 // ... 6 } 7 f(); 8})();

は下記と同じです。

JavaScript

1(funciton(){ 2 var a; 3 a = 1; // ① 4 function f() { 5 var a; 6 a = a || {}; // ② 7 // ... 8 } 9 f(); 10})();

つまり、①で代入しているaと②で参照しているaは同名の別の変数であり、①が②に影響を与えることはありません。もし、そのような動作を期待しているのであれば、全くの無意味としか言わざるを得ません。

####4. グローバル変数として定義している。

こちらも同じです。

JavaScript

1a = 1; 2function f() { 3 var a = a || {}; 4 // ... 5} 6f();

は下記と同じです。

JavaScript

1a = 1; 2function f() { 3 var a; 4 a = a || {}; 5 // ... 6} 7f();

関数内のaがグローバル変数aを見に行く事はありません。varにより関数内のaはその関数限定のローカル変数であることを細書し宣言してしまっているからです。グローバル変数がどのように変化しても、関数内のaに影響をあてることは無く、それを期待しているのであれば、無意味です。

####5. 他ファイルでグローバル変数として定義している。

scriptタグで単純に二つのJavaScriptファイルを読み込んだ場合は、グローバル変数が衝突する場合があります。その場合に、既にグローバル変数が定義されていれば、それをそのまま使うというのは有効のように見えます。

JavaScript

1var a = 1;

JavaScript

1var a = a || {}; 2// ...

しかし、このようにして衝突を回避するという考え方自体が間違っています。そもそも、グローバル変数が衝突しないように即時関数やモジュールベースの書き方を採用すべきです。

JavaScript

1(function() { 2 var a = a || {}; 3 // ... 4})();

即時関数の中に書いてしまえば、意味が無いことは既に述べたとおりです。

全体を即時関数にした場合、ライブラリなのでグローバル変数が定義できないとか思うかもしれませんが、グローバル変数はグローバルオブジェクトのプロパティに過ぎませんので、グローバル変数のプロパティとして定義すれば良いだけです。そのとき、varの出番はありませんので、該当のコードが現れる事はありません。

####6. 最初からグローバル変数として定義されている。

Polyfillに使う場合、既にグローバル変数があればオブジェクトを再設定する必要はありませんので、ある意味それは正しいように思えます。

しかし、それは完全なPolyfillとはいえません。理由はthink49さんの回答を見てください。また、グローバル変数名衝突回避のためにコード全体を即時関数で囲っているのであれば、varの所では必ず再設定になるため、意味がありません。グローバル変数を見たかったら、var a = window.a || {}と書く必要があるでしょう。

###まとめ

よって、私の結論は最初の文に戻ります。var a = a || {};というコードは、そもそもコードとしてどこかが不適切である(非推奨な方法を取っている)か、無意味な物です。そのため、極めて奇妙なコードに思えます。そのようなコードは良くないサンプルであると判断し、私としては、そのような事が書いてあるサイトや本自体を信頼しません。

投稿2017/08/04 13:18

編集2017/08/09 10:12
raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LanHma

2017/08/05 07:18

回答ありがとうございます! var a = a || {};が無意味な物と理解する事が出来ました。 様々なパターンでご説明いただきありがとうございます! 気持ちがすっきりしました!
Tak1016

2017/08/08 16:27

var a = a || {}; は無意味という内容は不適切なので評価を下げさせていただきました。
raccy

2017/08/08 21:43 編集

Tak1016さんが無意味では無いというのは、JavaScriptの単純な結合(モジュールベースやCommonJSなどを使っておらず、scriptタブによる複数呼び出しで対応)の場合の事でよろしいでしょうか? なの、私は、`var`がない`a = a || {}`や`window.a = window.a || {}`が無意味と言っているわけではありませんが、こちらまで無意味であると主張していると捉えてしまっていることでしょうか?
Tak1016

2017/08/09 00:35 編集

つまり無意味ではない状況も存在するということですよね? その状況について言及せずに冒頭、文末で無意味と断定している。 そしてそれがベストアンサーにされてしまったという悲劇ですね。
x_x

2017/08/09 01:22

質問者も回答者もずっと変数の宣言での話をしており、何の問題もないと思いますが?
think49

2017/08/09 01:32

var a = a || {}; が無意味ではない事例は私の回答で述べました。 このコードは ES3 互換コードなので、モジュールは関係ないと判断しています。
think49

2017/08/09 03:26

「衝突しない前提の論理」と「衝突前提の論理」の差は感じました。 そもそも論として「衝突すべきではありません」はあるのですが、「実際に衝突してしまった場合はどうする?(フェイルセーフ)」に対する一つの解だと思います。 私の結論としては「衝突したグローバル変数を truthy 判定する意味はありますが、型を厳密に判定する方が好ましい」で無意味とまではいいません。 この手の「緩い判定」を無意味と断じるのであれば、引数に与えられた変数 a を a = a || {}; も無意味(Object 型ではない可能性がある)ですし、var 文も無意味(再定義されない let, const を使うべき)になります。 コードの書き方は千差万別なので、ポリシーの差で片付けられる論理なら「非推奨(MAY NOT)」と私は書きます。 (「無意味」はMUST NOT並みに強い否定に読めます。)
raccy

2017/08/09 09:25

外部ファイルの話は後で追記しますが、その前に、一つだけ。私は"すべて"「無意味」と言っているわけでは無く、「無意味」"または"「不適切」と言っているだけです。「不適切」の表現ですが、think49さんのいう「非推奨」の意味と思ってください。 申し訳ありませんが、ES3は全く考慮していません。IE11すら捨てたい状況において、ES3も考慮するとなると、あれもできない、これもできない、で一昔のJavaScriptしか作れなくなりますので、JavaScriptを使う意義が見いだせないからです。
raccy

2017/08/09 10:19

追記しました。 そもそも、私の考えとしては、グローバル変数が衝突するような書き方(即時関数で囲まない、または、モジュールベースにしない)は(本番では)避けるべきとしています。それでも、ライブラリの場合はグローバル変数として定義する必要がありますが、その場合の衝突回避は単純では無い事はthink49さんの回答の通りなので、そちらを見ていただければと思います。 ということで、私としては無意味、**または**、不適切(非推奨)な書き方をしているのいずれかになると思っています。コードに意味があり、かつ、モダンなJavaScriptとして適切な書き方をしている例があれば、ご提示いただけると助かります。(ただ、ES3は環境が無くて、調べるのが大変なので、勘弁してください)
Tak1016

2017/08/09 10:38

拍手???? 私はなんでも屋さんなので古い環境のメンテとか頼まれてやったりするんですが、未だにIE8とか普通にあるんですよ。インフラも何もない地域に学校を建てるみたいな縛りの中で如何に良いものを作るか。職人は道具を選ばずです笑
guest

0

|| 演算子

JavaScript

1a || b;

|| は左辺が truthy なら左辺を返し、左辺が falsy なら右辺を返す演算子です。
一見、truthy な方を返すように見えますが、両方とも truthy なら左辺を返し、両方とも falsy なら右辺を返す点に注意が必要です。
Object 型は truthy なので左辺が {} なら左辺を返すことになります。

変数宣言の重複

JavaScript

1var a = a || {};

まず、前提としてこのコードは var を使う事に意味があります。
var は変数宣言の重複を許しますが、letconst は変数宣言の重複を許しません。

HTML

1<script> 2'use strict'; 3{ 4 let a = 1; 5 let a = a || 2; // SyntaxError: Identifier 'a' has already been declared 6} 7</script> 8<script> 9'use strict'; 10{ 11 const b = 1; 12 const b = b || 2; // SyntaxError: Identifier 'b' has already been declared 13} 14</script>

Polyfill

JavaScript

1var a = a || {};

このコードが有効となる状況として考えられるパターンは2つあります。
一つは Polyfill としての役割を持たせ、ネイティブコードと互換コードのどちらか一方を有効にする事です。

JavaScript

1var JSON = JSON || {parse: function parse () {}, stringify: function stringify () {}};

上記コードはブラウザが JSON を持っているならそのまま使用し、持っていないなら Polyfill コードを適用します。
ただし、ネイティブな JSON は {enumerable: false} ですが、var 宣言された JSON は {enumerable: true} なので厳密には異なります。
解決するには、Object.defineProperty() を使用する必要があります。

JavaScript

1Object.defineProperty(this, 'JSON', { 2 writable: true, 3 enumerable: false, 4 configurable: true, 5 value: {parse: function parse () {}, stringify: function stringify () {}} 6});

最も、JSON は ES5 仕様であり、Polyfill を適用するターゲットとなる実装は ES3 互換になるので、Object.defineProperty() はまだ実装されていません。
Object.defineProperty() が実装されていない以上、var 宣言の Polyfill で妥協するのは致し方ない側面はあります。
(ES6 の Polyfill なら Object.defineProperty() を使うべきでしょう。)

オブジェクトを共有する

もう一つは、グローバル変数が衝突した場合に、既存のオブジェクトを流用してプロパティを共有させる事で、変数の上書きを回避する事です。

JavaScript

1/** 2 * a-1.js 3 */ 4var a = {foo: 1}; 5 6/** 7 * a-2.js 8 */ 9var a = a || {}; 10a.piyo = 2;

a-1.js と a-2.js は別の動きをしますが、使用しているプロパティ名が衝突しない限りは共存できます。
勿論、プロパティ名が衝突する可能性がある以上、根本的な解決には至っていませんが、a-1.js と a-2.js の作者が同一人物である場合においては、衝突を回避する事は容易といえます。

ただ、実際のところ、他人が制作したライブラリとグローバル変数名が衝突してもオブジェクトを共有する意図でおまじない的にコードを書いている人が大半であるというのが私の認識です。
その場合、変数 a が truthy であっても Object 型であるとは限らないので、下記のような悲劇が起こる可能性があります。

JavaScript

1/** 2 * b.js (他作ライブラリ) 3 */ 4var a = true; 5 6/** 7 * a.js (自作ライブラリ) 8 */ 9var a = a || {}; 10a.piyo = 2; // TypeError: Cannot create property 'piyo' on boolean 'true'

他作ライブラリとのグローバル変数の衝突を危惧するのであれば、最低限、該当グローバル変数値が Object 型である事を保証しなければ意味がありません。

JavaScript

1/** 2 * b.js (他作ライブラリ) 3 */ 4var a = true; 5 6/** 7 * a.js (自作ライブラリ) 8 */ 9if (a && Object(a) !== a) { // 変数 a が truthy かつ Object 型でなければ 10 throw new TypeError(a + ' is not a object'); // TypeError: true is not a object 11} 12var a = a || {}; 13a.piyo = 2;

自作ライブラリが他作ライブラリの変数で上書きされる可能性はある為、変数を上書き出来ないように Object.defineProperty() で定義してやるとより安全になります。

HTML

1<script> 2'use strict'; 3/** 4 * a-1.js (自作ライブラリ) 5 */ 6if ('a' in this) { 7 if (Object(a) !== a) { 8 throw new TypeError(a + ' is not a object'); 9 } 10 11 a.foo = 1; 12} else { 13 Object.defineProperty(this, 'a', { 14 writable: false, 15 enumerable: false, 16 configurable: true, 17 value: {foo: 1} 18 }); 19} 20</script> 21<script> 22'use strict'; 23/** 24 * a-2.js (自作ライブラリ) 25 */ 26if ('a' in this) { 27 if (Object(a) !== a) { 28 throw new TypeError(a + ' is not a object'); 29 } 30 31 a.bar = 2; 32} else { 33 Object.defineProperty(this, 'a', { 34 writable: false, 35 enumerable: false, 36 configurable: true, 37 value: {bar: 2} 38 }); 39} 40 41console.log(a); // var value = {bar: 2}; 42</script> 43<script> 44/** 45 * b.js (他作ライブラリ) 46 */ 47var a = {piyo: 3, hoge: function () { return this.piyo; }}; // writable: false なので書き込みされない 48console.log(a); // {foo: 1, bar: 2} 49console.log(a.hoge()); // TypeError: a.hoge is not a function 50</script>

上記コードは分かりやすさ重視で書いていますが、a.foo = 1;value: {foo: 1} で二重に同じ初期化を強いるので保守性が落ちています。
実用のコードは下記のようになります。

HTML

1<script> 2'use strict'; 3/** 4 * a-1.js (自作ライブラリ) 5 */ 6(function () { 7 var value = {foo: 1}; 8 9 if ('a' in this) { 10 var a = this.a; 11 12 if (Object(a) !== a) { 13 throw new TypeError(a + ' is not a object'); 14 } 15 16 Object.assign(a, value); // ES6 (要 Polyfill) 17 } else { 18 Object.defineProperty(this, 'a', { 19 writable: false, 20 enumerable: false, 21 configurable: true, 22 value: value 23 }); 24 } 25}.call(this)); 26</script>

Object.defineProperty() と const

ES3 への配慮が不要なら、グローバル名前空間の衝突対策として、次の2つが有力な選択肢となります。

  • ES5 実装が対象なら、Object.defineProperty() を使う
  • ES6 実装が対象なら、let または const を使う

Object.defineProperty() の有効性は説明済みなので省くとして、ES6 では特に const が衝突検出器として有力です。
Object.defineProperty() による上書き禁止のコードでは上書きはできないものの、上書きを試みたタイミングでは何も発生しない静かなコードでした。

HTML

1<script> 2Object.defineProperty(this, 'a', { 3 writable: false, // 上書き禁止 4 enumerable: false, 5 configurable: true, 6 value: {foo: 1} 7}); 8</script> 9<script> 10var a = {bar: 2, piyo: function () { return this.bar; }}; // 上書き禁止だが、ここではエラーが発生しない 11console.log(a.bar); // undefined (ここでもエラーが発生しない) 12console.log(a.piyo()); // TypeError: a.piyo is not a function 13</script>

const再代入を禁止する為、上書きする事が出来ません。

HTML

1<script> 2'use strict'; 3const a = {foo: 1}; 4</script> 5<script> 6'use strict'; 7a = {bar: 2}; // TypeError: Assignment to constant variable. (再代入禁止) 8</script> 9<script> 10'use strict'; 11var a = {bar: 2}; // SyntaxError: Identifier 'a' has already been declared (再定義禁止) 12</script>

TypeErrorconst による再代入禁止、SyntaxError は再定義禁止による規定によるものです。
let も再定義禁止の為、var, let, const による同じ名前の変数宣言を防ぐ事が可能です。

なお、const は再代入は禁止されていますが、プロパティの書き換えは許容されている為、複数のスクリプト間で同じオブジェクトを共有する事は出来ます。

HTML

1<script> 2'use strict'; 3const a = {foo: 1}; 4</script> 5<script> 6'use strict'; 7a.bar = 2; // プロパティの書き換えは出来る 8console.log(a); // {foo: 1, bar: 2} 9</script>

型の判定

Object 型を期待する変数は Object 型もしくは Null 型を代入すべき変数です。

HTML

1<script> 2var a = 1; 3</script> 4<script> 5var a = a || {}; 6console.log(a); // 1 7</script>

期待に反して、変数 a には Number 型の値が代入されています。
この状況は、次のコードで改善されます。

HTML

1<script> 2var a = 1; 3</script> 4<script> 5if (Object(a) !== a) { 6 throw new TypeError(a + ' is not a object'); // TypeError: 1 is not a object 7} 8var a = {}; 9console.log(a); 10</script>

TypeError を発生させる事で Object 型以外の値が代入されている事が分かります。

まとめ

まとめると、次のようになると思います。

  • ES3 実装が対象なら、Polyfill もしくは複数の自作ライブラリ間でオブジェクトを共有する場合に var 宣言を使う
  • ES5 実装が対象なら、Object.defineProperty() を使う
  • ES6 実装が対象なら、let または const を使う

最も、Microsoft は2017/04/11(Windows Vista のサポート終了日)に IE10- のサポートを終了している為、ES3 に配慮する場面は少ないと思います。

ただし、「型の判定」節で触れている通り、var a = a || {}; は Object 型以外の値が代入するケースを排除できない問題があります。
判定条件が緩い為、Object() で正しく判定するコードがより好ましいといえます。

更新履歴

  • 2017/08/05 00:58 「Object.defineProperty() と const」を追記
  • 2017/08/09 10:56 const による再代入禁止のコード事例が再定義禁止になっていた為、再代入禁止のコードに修正
  • 2017/08/09 11:51 「型の判定」節を追記

Re: LanHma さん

投稿2017/08/04 15:10

編集2017/08/09 02:51
think49

総合スコア18162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LanHma

2017/08/05 07:16

回答ありがとうございます!使い方まで丁寧に教えていただき大変恐縮です!勉強になりました!ありがとうございます!
guest

0

論理和を利用した「短絡評価」というテクニックです。
主に未定義の変数を確実に初期化するために利用されます。
変数aが定義済みで具体的なオブジェクトが入っていれば、自分自身を代入なので、実質そのまま素通りします。
変数aが 0,null,undefined,false,""などだった場合、値としてはfalseとして評価されるため、||の右側である{}が代入されます。
三項演算子で表現したほうがわかりやすいかもしれませんね。

javascript

1a = a ? a : {};

やっているのは、こういうことです。
ですので、

javascript

1var a = {}

とは、明確に違います。

わかりやすそうな使用例は、こんな感じです。

javascript

1function Paint(image,x,y,scale){ 2 x = x || 0; 3 y = y || 0; 4 scale = scale || 1; 5 // なんやかんや 6}

第一引数imageを、なんやかんや処理して描画するメソッドを想像してください。
第二引数以降は、必須ではありません。

Paint("hoge.png")のように呼び出された場合、x,y,scaleにはすべてundefinedが入っています。
そこで、この短絡評価を通ることで、それぞれ0,0,1に初期化されますので、これ以降の処理で細かい分岐処理なしで処理が可能になるのです。

投稿2017/08/04 09:12

zohnam

総合スコア1441

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hellomartha

2017/08/04 10:31

質問の趣旨とずれるかもしれませんが 変数宣言時にその変数で短絡評価するのって意味あるんですかね var a = a || {} aが多重に定義されている前提?
zohnam

2017/08/04 10:55

だと思います。一般的なaやbみたいな変数でそれをやるのに意味があるとは思えませんけどね。なので、そこは私もそのソースの意図はよくわかりません。 雰囲気で似てるのでは、HTML5の最新機能で、糞ブラウザ(IEのことです)だと実装されてないせいでエラーが出て止まるのを避けるため、みたいな初期化方法をたまにみかけますね。 var createObjectURL = window.URL.createObjectURL || function(){}; こういう感じで、最悪でも空メソッドでなにもしないだけにしておきます。jQueryプラグインのソースなんかで、似たようなコードを見かけます。
hellomartha

2017/08/04 11:14

なるほど場面によっては意味ありえますね、本筋から逸れた質問にありがとうございます
LanHma

2017/08/05 07:14

使用例まで記載いただき恐縮です!ありがとうございます! 勉強になりました!
guest

0

javascriptを使うとき、いろいろな人が開発して公開しているjsを寄せ集めて使いますよね?

some.js

javascript

1var a = { name: "piyo", say : function() { return "I am " + this.name } }; 2

any.js

javascript

1a = { x : 1, y : 3 }; 2 3//省略すると document.aになる document.aのつもりで書いた

と宣言されていると
some.jsのaがany.jsで上書きされて動かなくなってしまいます。

aという名前の変数をグローバルに宣言する安易な実装をしたjsファイルが集まるとバグを引き起こすのです。

aという変数を自分で宣言しなくても、minifyというjsを圧縮するツールによって変数を短くされてしまうこともあります。

短い変数名を使っている有名なライブラリもあります。
$ (jQuery)
_ (underscore)

なので、開発者は衝突しないように、色々な工夫をするのです。

###namespaceパターン
ライブラリを作るときに他のライブラリと変数が衝突しないように
objectの階層を作る。

javascript

1var jp = jp || {}; 2jp.co = jp.co || {}; 3jp.co.piyo = jp.co.piyo || {}; 4//このpiyoに対して機能を追加していく

###即時関数パターン

javascript

1//関数を宣言して即実行 2(function() { 3 var piyo = jp.co.piyo; 4 var xxx = piyo.getXXX(); 5})();

書き直すと

javascript

1var f = funtion() { 2 var piyo = jp.co.piyo; 3 var xxx = piyo.getXXX(); 4}; 5 6f(); //これを一行で書いた

関数の内部で宣言した変数は外部とは衝突しない。

投稿2017/08/04 12:56

Tak1016

総合スコア1408

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LanHma

2017/08/05 07:14

回答ありがとうございます!勉強になりました!
himejiy3

2017/08/08 15:57

私も初心者を脱していない者で大変恐縮なのですが、この質問の回答に関しては こちらのTak1016さんとthink49さんの回答が一番近いと思います。 これは中規模以上のクラスライブラリを作成する場合には、必須とも言える手段だそうです。 「JavaScript 名前空間」で検索してみてください。 ベストアンサーの評価を下げるほどではないのですが、 本格的な大規模開発においてはnamespaceは必要な知識とのことなので、 後からここに来た人が「そっかー、無意味なんだー」で終わらないようにコメントさせていただきました。
guest

0

論理 OR (||)

expr1 || expr2

expr1 を true と見ることができる場合は、expr1 を返します。そうでない場合は、expr2 を返します。
論理演算子 - JavaScript | MDN

aに何か入っていればそのまま、何も入っていなければ{}ということです。

投稿2017/08/04 09:06

Lhankor_Mhy

総合スコア36074

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LanHma

2017/08/05 07:13

回答ありがとうございます!勉強になりました!
guest

0

それなら初めから

変数a がすでに有る場合は使って、無かったら{}というコードでは。

投稿2017/08/04 09:07

kei344

総合スコア69400

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LanHma

2017/08/05 07:13

回答ありがとうございます!勉強になりました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問