1048

オブジェクトと関数が他の同じ名前のオブジェクトと関数によって上書きされないように、JavaScript で名前空間を作成するにはどうすればよいですか? 私は以下を使用しました:

if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}

これを行うためのよりエレガントまたは簡潔な方法はありますか?

4

29 に答える 29

1060

I use the approach found on the Enterprise jQuery site:

Here is their example showing how to declare private & public properties and functions. Everything is done as a self-executing anonymous function.

(function( skillet, $, undefined ) {
    //Private Property
    var isHot = true;

    //Public Property
    skillet.ingredient = "Bacon Strips";

    //Public Method
    skillet.fry = function() {
        var oliveOil;

        addItem( "\t\n Butter \n\t" );
        addItem( oliveOil );
        console.log( "Frying " + skillet.ingredient );
    };

    //Private Method
    function addItem( item ) {
        if ( item !== undefined ) {
            console.log( "Adding " + $.trim(item) );
        }
    }
}( window.skillet = window.skillet || {}, jQuery ));

So if you want to access one of the public members you would just go skillet.fry() or skillet.ingredients.

What's really cool is that you can now extend the namespace using the exact same syntax.

//Adding new Functionality to the skillet
(function( skillet, $, undefined ) {
    //Private Property
    var amountOfGrease = "1 Cup";

    //Public Method
    skillet.toString = function() {
        console.log( skillet.quantity + " " +
                     skillet.ingredient + " & " +
                     amountOfGrease + " of Grease" );
        console.log( isHot ? "Hot" : "Cold" );
    };
}( window.skillet = window.skillet || {}, jQuery ));

The third undefined argument

3 番目のundefined引数は、 value の変数のソースですundefined。今日でも関連性があるかどうかはわかりませんが、古いブラウザー/JavaScript 標準 (ecmascript 5、javascript < 1.8.5 ~ firefox 4) を使用している間、グローバル スコープ変数undefinedは書き込み可能であるため、誰でもその値を書き換えることができます。undefined3 番目の引数 (値が渡されない場合) は、名前空間/関数をスコープとする名前付き変数を作成します。名前空間を作成したときに値が渡されなかったため、デフォルトで value に設定されますundefined

于 2011-05-10T08:28:07.430 に答える
798

私はこれが好き:

var yourNamespace = {

    foo: function() {
    },

    bar: function() {
    }
};

...

yourNamespace.foo();
于 2009-05-19T08:22:29.827 に答える
354

それを行う別の方法は、オブジェクトリテラル形式よりも少し制限が少ないと私が考えるものですが、これは次のとおりです。

var ns = new function() {

    var internalFunction = function() {

    };

    this.publicFunction = function() {

    };
};

上記はモジュール パターンによく似ており、好むと好まざるとにかかわらず、オブジェクト リテラルの厳密な構造を回避しながら、すべての関数をパブリックとして公開できます。

于 2009-05-19T08:39:28.483 に答える
158

これを行うためのよりエレガントまたは簡潔な方法はありますか?

はい。例えば:

var your_namespace = your_namespace || {};

その後、あなたが持つことができます

var your_namespace = your_namespace || {};
your_namespace.Foo = {toAlert:'test'};
your_namespace.Bar = function(arg) 
{
    alert(arg);
};
with(your_namespace)
{
   Bar(Foo.toAlert);
}
于 2010-05-26T11:34:01.460 に答える
97

私は通常、クロージャーでそれを構築します:

var MYNS = MYNS || {};

MYNS.subns = (function() {

    function privateMethod() {
        // Do private stuff, or build internal.
        return "Message";
    }

    return {
        someProperty: 'prop value',
        publicMethod: function() {
            return privateMethod() + " stuff";
        }
    };
})();

これを書いて以来、何年にもわたって私のスタイルは微妙に変化しており、今では次のようにクロージャーを書いていることに気づきました。

var MYNS = MYNS || {};

MYNS.subns = (function() {
    var internalState = "Message";

    var privateMethod = function() {
        // Do private stuff, or build internal.
        return internalState;
    };
    var publicMethod = function() {
        return privateMethod() + " stuff";
    };

    return {
        someProperty: 'prop value',
        publicMethod: publicMethod
    };
})();

このようにして、パブリック API と実装が理解しやすくなります。return ステートメントは、実装へのパブリック インターフェイスであると考えてください。

于 2011-05-20T20:07:18.990 に答える
59

JavaScriptの異なるファイルを作成し、後でそれらをアプリケーションで結合することも結合しないこともできるため、それぞれが他のファイルの作業を損なうことなく名前空間オブジェクトを回復または構築できる必要があります...

1つのファイルが名前空間を使用することを意図している可能性がありますnamespace.namespace1

namespace = window.namespace || {};
namespace.namespace1 = namespace.namespace1 || {};

namespace.namespace1.doSomeThing = function(){}

別のファイルが名前空間を使用したい場合がありますnamespace.namespace2

namespace = window.namespace || {};
namespace.namespace2 = namespace.namespace2 || {};

namespace.namespace2.doSomeThing = function(){}

これらの2つのファイルは、衝突することなく共存または分離できます。

于 2010-11-09T04:27:21.893 に答える
53

これは、Stoyan Stefanov が彼のJavaScript パターンの本でそれを行う方法であり、私が非常に優れていることがわかりました (また、自動生成された API ドキュメントを許可するコメントを行う方法と、カスタム オブジェクトのプロトタイプにメソッドを追加する方法も示しています)。

/**
* My JavaScript application
*
* @module myapp
*/

/** @namespace Namespace for MYAPP classes and functions. */
var MYAPP = MYAPP || {};

/**
* A maths utility
* @namespace MYAPP
* @class math_stuff
*/
MYAPP.math_stuff = {

    /**
    * Sums two numbers
    *
    * @method sum
    * @param {Number} a First number
    * @param {Number} b Second number
    * @return {Number} Sum of the inputs
    */
    sum: function (a, b) {
        return a + b;
    },

    /**
    * Multiplies two numbers
    *
    * @method multi
    * @param {Number} a First number
    * @param {Number} b Second number
    * @return {Number} The inputs multiplied
    */
    multi: function (a, b) {
        return a * b;
    }
};

/**
* Constructs Person objects
* @class Person
* @constructor
* @namespace MYAPP
* @param {String} First name
* @param {String} Last name
*/
MYAPP.Person = function (first, last) {

    /**
    * First name of the Person
    * @property first_name
    * @type String
    */
    this.first_name = first;

    /**
    * Last name of the Person
    * @property last_name
    * @type String
    */
    this.last_name = last;
};

/**
* Return Person's full name
*
* @method getName
* @return {String} First name + last name
*/
MYAPP.Person.prototype.getName = function () {
    return this.first_name + ' ' + this.last_name;
};
于 2012-04-22T15:44:01.303 に答える
32

これは、user106826 の Namespace.js へのリンクのフォローアップです。プロジェクトはGitHubに移動したようです。現在はsmith/namespacedotjsです。

私はこの単純な JavaScript ヘルパーを自分の小さなプロジェクトに使用してきましたが、これまでのところ、名前空間の処理とモジュール/クラスのロードを処理するのに十分な軽量でありながら用途が広いようです。グローバル名前空間だけでなく、自分の選択した名前空間にパッケージをインポートできるようになれば素晴らしいことですが... はぁ、それは問題外です。

名前空間を宣言してから、その名前空間でオブジェクト/モジュールを定義できます。

Namespace('my.awesome.package');
my.awesome.package.WildClass = {};

もう 1 つのオプションは、名前空間とその内容を一度に宣言することです。

Namespace('my.awesome.package', {
    SuperDuperClass: {
        saveTheDay: function() {
            alert('You are welcome.');
        }
    }
});

その他の使用例については、ソースの example.js ファイルを参照してください。

于 2010-08-27T23:15:58.240 に答える
29

サンプル:

var namespace = {};
namespace.module1 = (function(){

    var self = {};
    self.initialized = false;

    self.init = function(){
        setTimeout(self.onTimeout, 1000)
    };

    self.onTimeout = function(){
        alert('onTimeout')
        self.initialized = true;
    };

    self.init(); /* If it needs to auto-initialize, */
    /* You can also call 'namespace.module1.init();' from outside the module. */
    return self;
})()

プライベートにしたい場合は、必要に応じてlocal変数を宣言しsame、 likeselfおよび assignすることができます。local.onTimeout

于 2012-05-10T11:44:51.063 に答える
15

名前空間を提供する単純な関数を宣言できます。

function namespace(namespace) {
    var object = this, tokens = namespace.split("."), token;

    while (tokens.length > 0) {
        token = tokens.shift();

        if (typeof object[token] === "undefined") {
            object[token] = {};
        }

        object = object[token];
    }

    return object;
}

// Usage example
namespace("foo.bar").baz = "I'm a value!";
于 2012-04-28T14:03:37.103 に答える
9

Erlang のモジュールにインスパイアされた名前空間を作成しました。これは非常に機能的なアプローチですが、これが最近の私の JavaScript コードの書き方です。

クロージャーにグローバル名前空間を与え、そのクロージャー内で定義されたセット関数を公開します。

(function(){

  namespace("images", previous, next);
  // ^^ This creates or finds a root object, images, and binds the two functions to it.
  // It works even though those functions are not yet defined.

  function previous(){ ... }

  function next(){ ... }

  function find(){ ... } // A private function

})();
于 2010-07-04T04:25:42.330 に答える
9

私はパーティーに 7 年遅れていますが、8 年前にかなりの作業を行いました。

ネストされた複数の名前空間を簡単かつ効率的に作成して、複雑な Web アプリケーションを整理して管理しやすくすると同時に、JavaScript グローバル名前空間を尊重し (名前空間の汚染を防ぎます)、名前空間パス内の既存のオブジェクトを破壊しないようにすることが重要です。 .

上記から、これは2008年頃の私の解決策でした:

var namespace = function(name, separator, container){
  var ns = name.split(separator || '.'),
    o = container || window,
    i,
    len;
  for(i = 0, len = ns.length; i < len; i++){
    o = o[ns[i]] = o[ns[i]] || {};
  }
  return o;
};

これは名前空間を作成するのではなく、名前空間を作成する機能を提供します。

これは、縮小されたワンライナーに要約できます。

var namespace=function(c,f,b){var e=c.split(f||"."),g=b||window,d,a;for(d=0,a=e.length;d<a;d++){g=g[e[d]]=g[e[d]]||{}}return g};

使用例:

namespace("com.example.namespace");
com.example.namespace.test = function(){
  alert("In namespaced function.");
};

または、1 つのステートメントとして:

namespace("com.example.namespace").test = function(){
  alert("In namespaced function.");
};

どちらも次のように実行されます。

com.example.namespace.test();

古いブラウザのサポートが必要ない場合は、更新されたバージョン:

const namespace = function(name, separator, container){
    var o = container || window;
    name.split(separator || '.').forEach(function(x){
        o = o[x] = o[x] || {};
    });
    return o;
};

さて、私namespaceはグローバル名前空間自体に公開することに慎重です。(ベース言語がこれを提供していないのは残念です!)したがって、私は通常、次のようなクロージャーでこれを自分で使用します。

(function(){
	const namespace = function(name, separator, container){
		var o = container || window;
		name.split(separator || '.').forEach(function(x){
			o = o[x] = o[x] || {};
		});
		return o;
	};
	const ns = namespace("com.ziesemer.myApp");
	
	// Optional:
	ns.namespace = ns;
	
	// Further extend, work with ns from here...
}());

console.log("\"com\":", com);

大規模なアプリケーションでは、これを定義する必要があるのは、ページの読み込みの開始時に 1 回だけです (クライアント ベースの Web アプリの場合)。追加のファイルは、保持されている場合は名前空間関数を再利用できます (上記の「オプション」として含まれています)。最悪の場合、この関数が数回再宣言された場合、数行のコードしかなく、縮小された場合はそれ以下になります。

于 2016-11-28T00:05:51.013 に答える
8

いくつかのライブラリを別のプロジェクトに移植し、常に最上位の(静的に名前が付けられた)名前空間を変更する必要があった後、名前空間を定義するためにこの小さな(オープンソース)ヘルパー関数を使用するように切り替えました。

global_namespace.Define('startpad.base', function(ns) {
    var Other = ns.Import('startpad.other');
    ....
});

利点の説明は私のブログ投稿にあります。ここでソースコードを入手できます。

私が本当に気に入っている利点の1つは、ロード順序に関してモジュールを分離できることです。ロードする前に外部モジュールを参照できます。また、取得したオブジェクト参照は、コードが利用可能になったときに入力されます。

于 2010-03-27T06:38:01.153 に答える
8

名前空間には次の構文を使用します。

var MYNamespace = MYNamespace|| {};

 MYNamespace.MyFirstClass = function (val) {
        this.value = val;
        this.getValue = function(){
                          return this.value;
                       };
    }

var myFirstInstance = new MYNamespace.MyFirstClass(46);
alert(myFirstInstance.getValue());

jsfiddle: http://jsfiddle.net/rpaul/4dngxwb3/1/

于 2015-02-04T22:45:03.667 に答える
2

Jaco Pretorius のソリューションが気に入っていますが、「this」キーワードをモジュール/名前空間オブジェクトに向けることで、もう少し便利にしたかったのです。私のバージョンのスキレット:

(function ($, undefined) {

    console.log(this);

}).call(window.myNamespace = window.myNamespace || {}, jQuery);
于 2014-12-02T15:39:28.063 に答える
1

このように独立して使用できます。

var A = A|| {};
A.B = {};

A.B = {
    itemOne: null,
    itemTwo: null,
};

A.B.itemOne = function () {
    //..
}

A.B.itemTwo = function () {
    //..
}
于 2015-08-21T05:23:26.393 に答える
1

Makefile を使用している場合は、これを行うことができます。

// prelude.hjs
billy = new (
    function moduleWrapper () {
    const exports = this;

// postlude.hjs
return exports;
})();

// someinternalfile.js
function bob () { console.log('hi'); }
exports.bob = bob;

// clientfile.js
billy.bob();

Makefile の 1 行を削除するだけで大​​量のコードを効果的にコメントアウトできるため、約 1000 行になったら Makefile を使用することを好みます。物をいじるのが簡単になります。また、この手法を使用すると、名前空間はプレリュードに 1 回しか表示されないため、簡単に変更でき、ライブラリ コード内で繰り返し続ける必要がありません。

makefile を使用する場合のブラウザーでのライブ開発用のシェル スクリプト:

while (true); do make; sleep 1; done

これを make タスク 'go' として追加すると、'make go' を実行して、コーディング中にビルドを最新の状態に保つことができます。

于 2011-04-13T14:36:21.267 に答える
1

Ionuş G. Stan の回答のかなりのフォローアップですがvar ClassFirst = this.ClassFirst = function() {...}、JavaScript のクロージャー スコープを利用して、同じ名前空間内のクラスの名前空間の乱雑さを軽減することで、コードを整理することの利点を示しています。

var Namespace = new function() {
    var ClassFirst = this.ClassFirst = function() {
        this.abc = 123;
    }

    var ClassSecond = this.ClassSecond = function() {
        console.log("Cluttered way to access another class in namespace: ", new Namespace.ClassFirst().abc);
        console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc);
    }
}

var Namespace2 = new function() {
    var ClassFirst = this.ClassFirst = function() {
        this.abc = 666;
    }

    var ClassSecond = this.ClassSecond = function() {
        console.log("Cluttered way to access another class in namespace: ", new Namespace2.ClassFirst().abc);
        console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc);
    }
}

new Namespace.ClassSecond()
new Namespace2.ClassSecond()

出力:

Cluttered way to access another class in namespace: 123
Nicer way to access a class in same namespace: 123
Cluttered way to access another class in namespace: 666
Nicer way to access a class in same namespace: 666
于 2015-06-13T04:31:36.797 に答える
1

パッケージ/ユニットが他の言語で行うように、もう少し機能する別の名前空間ライブラリを作成しました。JavaScript コードのパッケージを作成し、他のコードからそのパッケージを参照できます。

ファイル hello.js

Package("hello", [], function() {
  function greeting() {
    alert("Hello World!");
  }
  // Expose function greeting to other packages
  Export("greeting", greeting);
});

ファイル Example.js

Package("example", ["hello"], function(greeting) {
  // Greeting is available here
  greeting();  // Alerts: "Hello World!"
});

ページに含める必要があるのは 2 番目のファイルだけです。その依存関係 (この例ではhello.jsファイル) は自動的に読み込まれ、それらの依存関係からエクスポートされたオブジェクトは、コールバック関数の引数を設定するために使用されます。

関連するプロジェクトはPackages JSにあります。

于 2011-02-06T10:42:05.197 に答える
0

私の習慣は、関数 myName()をプロパティ ストレージとして使用し、次にvar myNameを「メソッド」ホルダーとして使用することです...

これが正当であるかどうかにかかわらず、私を打ち負かしてください! 私は常に PHP ロジックに依存しており、物事は単純に機能します。:D

function myObj() {
    this.prop1 = 1;
    this.prop2 = 2;
    this.prop3 = 'string';
}

var myObj = (
 (myObj instanceof Function !== false)
 ? Object.create({

     $props: new myObj(),
     fName1: function() { /* code..  */ },
     fName2: function() { /* code ...*/ }
 })
 : console.log('Object creation failed!')
);

if (this !== that) myObj.fName1(); else myObj.fName2();

また、「その逆」の方法でオブジェクトを作成する前に確認することもできます。これははるかに優れています

function myObj() {
    this.prop1 = 1;
    this.prop2 = 2;
    this.prop3 = 'string';
}

var myObj = (
    (typeof(myObj) !== "function" || myObj instanceof Function === false)
    ? new Boolean()
    : Object.create({
        $props: new myObj(),
        init: function () { return; },
        fName1: function() { /* code..  */ },
        fName2: function() { /* code ...*/ }
    })
);

if (myObj instanceof Boolean) {
    Object.freeze(myObj);
    console.log('myObj failed!');
    debugger;
}
else
    myObj.init();

これへの参照: JavaScript: Object.create() によるオブジェクトの作成

于 2015-04-16T13:38:02.330 に答える