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

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

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

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

Q&A

解決済

2回答

15159閲覧

JavaScriptの名前空間の書き方

nekojiro

総合スコア43

JavaScript

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

2グッド

3クリップ

投稿2017/07/10 11:34

###前提・実現したいこと
名前空間について調べたのですが、色々な書き方が有ったり古かったりするのでどう書けばいいのかよくわかりません。es6で書く場合はこんな感じでいいですか。

###該当のソースコード

javascript

1const namespace = {}; 2namespace.a = 'a';// 変数 3namespace.function = function() {// 関数 4 console.log('test'); 5}; 6namespace.class = class {// クラス 7 constructor(params) { 8 this.params = params; 9 } 10};
x_x, AkifumiShimoji👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

ES5以前のJavaScriptにおいて、名前空間(namespace)という概念がそもそもありませんでした。各ファイルは単に結合されるだけだったため、グローバル変数の重複等による諸問題が発生する状態でした。その回避のために即時関数の使用や擬似的な名前空間の作成等のテクニックが編み出されました。

ES6(ES2015)から名前空間の概念が追加されました。ただ、ここで追加された名前空間は、一つのファイルないで名前空間を分けるという手法では無く、複数のファイルについて、それぞれが名前空間を持つ方式です。これがES6から追加されたモジュール(module)です。

ES6からモジュールとしてスクリプトファイルを読み込むという動作ができるようになりました。これまで、JavaScriptをHTML内で羅列した場合、それは単なるファイルの結合に過ぎませんでした。しかし、モジュールベースになった場合、それぞれが独立し、必要なものだけをやり取りできるようにしました。モジュールは次の点で通常のスクリプトファイルとは異なります。

  1. トップレベルのvar変数定義や関数定義がグローバルオブジェクトのプロパティ(グローバル変数)にはなりません。グローバルオブジェクトのプロパティとして明示的に作成しない限り、ファイル間で変数名や関数名の重複は発生しません
  2. 指定した変数、関数、クラスしか公開されません。トップレベルの変数であっても、公開しなければ、アクセス方法がありません。
  3. 自動的にstrictモードになります。'use strict';の汚染もありません。

このように、スクリプトファイル一つ一つが独自の名前空間を作成し、公開された名前を通してしか、やり取りできないようにしています。これがモジュールであり、ES6から追加された名前空間です。

モジュールの公開や読み込みにはexportimportという新しい構文を使用します。exportでそのファイルにある変数等についてどれを公開するのか指定し、importで指定した名前で他のファイルをモジュールとして読み込みます。

まずは、公開する側を見てみましょう。"myNamespace.js"というファイルを次のように作ってみます。

JavaScript

1var x = 'ex' 2export var a = 'a';// 変数 3export function f() {// 関数 4 console.log(x); 5}; 6export class K {// クラス 7 constructor(params) { 8 this.params = params; 9 } 10};

これを読み込んで、使用するには次のように書きます。

JavaScript

1import * as myNS from './myNamespace.js'; 2var x = 'in' 3console.log(myNS.a); // => 'a' 4myNS.f(); // => 'ex' 5let k = new myNS.K(0); 6console.log(k.params); // => 0 7console.log(x); // => 'in'

注目して欲しいのは、varで宣言されたxです。もし、この二つのファイルが単なる結合であれば、xは重複しているため、同じ物になるはずです。しかし、myNS.f()での出力は'ex'ですし、その後のxは'in'と違っています。これは、二つのファイルでxはそれぞれ別の物として扱われるからです。つまり、名前空間がファイルによって異なると言うことです。

"myNamespace.js"のうち、直接アクセスできるのはexportで明示的に公開しているafKに限定されます。import文は色々書き方があるのですが、今回はmyNSを最初に付けた形でそれらにアクセスするという風にしました。これで、公開された各変数、関数、クラスにアクセスできるようになり、また、それらが他のものと被ることもありません。

では、これはどうやって使えば良いのかというと、とっても簡単です。<script type="module">というようにscriptタグのtype属性に"module"を指定するだけで、通常のJavaScriptではなく、このモジュールベースのJavaScriptとしてブラウザが読み込んでくれます。自動的にstrictモードになるなど、嬉しい機能が満載ですので、使わないという選択肢は無いでしょう。

ここで、残念なお知らせがあります。この素晴らしいモジュールの機能ですが、2017年7月11日現在正式に対応しているブラウザはSafariのみです。対応表を見ると、Edge、Firefox、Chromeは実験的に対応しているので、そのうち使えるようになりますが、IEが対応することはありません。なぜなら、IEの開発は既に終了しているからです。IEを捨てるという素敵な決断ができない場合はどうすれば良いのでしょうか?

ご安心ください。Babelで変換して、WebpackやBrowserifyで結合すれば同じ事ができます。Babelはrequire等を用いたCommonJSの形式にimportexportを変換してくれます。あとは、CommonJSに対応したツールで一つにまとめれば良いのです。このとき、モジュール特有の名前空間も考慮して、一つにまとめてくれるので、IEでも(たぶん)うまく動いてくれるでしょう。

もうひとつ。Node.jsもまだ未対応です。ただ、こちらはそのうち対応する可能性が高いですが、それまでは同じくBabelで変換するしかありません。

投稿2017/07/11 11:25

raccy

総合スコア21735

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

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

zohnam

2017/07/14 10:59

IEってやっぱり窓から投げ捨てるべき存在ですよね…
guest

0

typescriptをjavascriptに変換すると以下のようなコードとなります。
nekojiroさんのコードでも大筋問題はないと思います。

typescript

1namespace hoge { 2 const _a = 'a'; 3 4 const _func = () => { 5 console.log('func'); 6 } 7 8 export class _class { 9 constructor(params) { 10 this.params = params; 11 } 12 } 13}

javascript

1var hoge; 2(function (hoge) { 3 var _a = 'a'; 4 var _func = function () { 5 console.log('func'); 6 }; 7 var _class = (function () { 8 function _class(params) { 9 this.params = params; 10 } 11 return _class; 12 }()); 13 hoge._class = _class; 14})(hoge || (hoge = {}));

投稿2017/07/10 13:43

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問