27

私は図書館を書いています。現在、私はすべてを次のような単一の.jsファイルに書き込んでいます。

function doThis() {}
var thisVar = 5;

それが正しいかどうかわからなかったので、私は考えました:

function Lib() {
  this.doThis = function() {}
  this.thisVar = 5;
}

var lib = new Lib();

次に、メインプログラムファイルで、「lib.thisVar」や「lib.doThis();」など、すべてを「lib。」で呼び出す必要があります。

どちらが良いか、または両方とも受け入れられるアイデアはありますか?前もって感謝します。

4

8 に答える 8

26

グローバル名前空間が乱雑にならないように、次のような構造を使用します。

var MyLib = {
    vars: {
        var1: 'value1',
        var2: 'value2'
    },
    func1: function () {
        return this.vars.var1;
    },
    func2: function () {
        alert("This is func2");
    }
};

MyLib.func1();
MyLib.func2();

すべての変数を独自のサブオブジェクトに配置したことに気付くでしょう。これは、読みやすく、開発しやすいようにするためだけに行われます。


編集1:

これが私が使用する別の方法です

var MyLib = (function MyLib() {
    var _privateVars = {
        "someVar": "This value made public by `someMethod`",
        "privateVar": "Can't see this value"
    };

    // Return the constructor
    return function MyLibConstructor() {
        var _this = this; // Cache the `this` keyword

        _this.someMethod = function () {
            // Access a private variable
            return _privateVars.someVar;
        };

        _this.someOtherMethod = function () {
            // Some other functionality
        };
    };
}());

var myLib = new MyLib(); // invoke

console.log( myLib.someMethod() );

この構造体はJSクロージャとコンストラクター関数を利用しているため、プライベート変数をプライベートに保つのは簡単です。

編集2:

さらに、コンストラクターを返さない別のクロージャー設定も使用しました(例var x = new MyLib();)。

(function(window) {
    var _private = {},
        methods = {},
        topic, init;

    methods.set = function(value) {
        // Set the property & value
        _private[topic] = value;
        return this;
    };

    // A simple get method
    methods.get = function(callback) {
        var response = null;

        // Return the value of topic (property) in a callback
        if (!!callback && typeof callback === 'function') {
            if (_private.hasOwnProperty(topic)) {
                response = _private[topic];
            }
            callback.call(this, response);
        }
        return this;
    };

    // Init method setting the topic and returning the methods.
    init = function(_topic) {
        topic = _topic;

        return methods;
    };

    // Exposure when being used in an AMD environment, e.g. RequireJS
    if (typeof define === 'function' && define.amd) {
        define(function() {
            return init;
        });
        return;
    }

    // Exposure when being used with NodeJS
    if ('undefined' !== typeof module && module.exports) {
        module.exports = init;
        return;
    }

    // Last-in-the-line exposure to the window, if it exists
    window.myLib = init;

    // This line either passes the `window` as an argument or
    // an empty Object-literal if `window` is not defined.
}(('undefined' !== typeof window) ? window : {}));

そしてそれが実際に動作するのを見るには:

myLib('something').set('made public, outside of the closure by the `get` method');

myLib('something').get(function(a){
  console.log(a);
});

myLibまた、実行されている場所と含まれている方法を考慮して、私が公開している方法も確認してください。

編集3(2017年7月):

moduleフルスタック(w / Node.js)JavaScriptエンジニアとして、そしてBrowserifyの登場として、マルチファイル(分離された、より小さな)をコンパイルするためのビルドシステムとしてGulpまたはGruntのいずれかを利用するNodejsスタイルのパターンの使用を強くお勧めしますコードのビット)を1つのライブラリに。

このモデルは、より機能的なアプローチを促進するのに役立ち、開発者がライブラリ内のより一般的な機能を個別のファイルに抽象化できるようにし、開発をはるかに容易にします。

ああ、ES6を使って!

// file: src/divideIntByFour.js

const divideIntByFour = (int) => {
    return int / 4;
};

module.exports = divideIntByFour;

...簡略化された例として

于 2012-11-28T13:35:07.213 に答える
11

JavaScriptモジュールのパターンを見てください。

http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth

ライブラリをrequire.jsと互換性を持たせることを検討できます。これは、まさにこの種のことを行うためのフレームワークです。

http://requirejs.org

于 2012-11-28T13:33:21.500 に答える
9

理論的には両方とも許容されます。ただし、どちらも、アプリケーションで使用されている他のパーツ/ライブラリとの名前の衝突のリスクがあります。

前者の場合、個々の関数の名前の衝突のリスクがありますが、後者の場合、ライブラリラッパー(Lib)に選択した関数の名前の衝突のリスクがあります。

推奨される方法は、次のページに示すように、それらを別の名前空間にラップすることです。

http://frugalcoder.us/post/2010/02/11/js-classes.aspx

于 2012-11-28T13:31:12.603 に答える
3

はい、後者のアプローチは、多くのグローバル変数(「グローバルスコープ汚染」)を作成しないが、オブジェクト上でそれらの名前空間を作成するため、より優れています。

ただし、コンストラクター(Lib)は必要ありません。インスタンス化するのlibは1回だけです(シングルトンパターンに従います)。プロトタイプは必要ありません。代わりに、単純なオブジェクトリテラルを使用してください。

var lib = {
    doThis: function() {
    },
    thisVar: 5
};

プライベート(静的ではありますが)変数、およびより優れたコード編成については、モジュールパターン(またはここ)も参照してください。

var lib = (function(){
    var thisVar = 5;
    function doThis() {}
    return { // "export"
        doThat: doThis
    };
})();
于 2012-11-28T13:32:19.633 に答える
2

投稿は古いですが、おそらく私の2セントが役立つかもしれません。私はこれを複数のライブラリで見て実行しました:

nameOfLibrary = function() { //name of library needs to be unique enough not to conflict with anyones code
  nameOfLibrary = {};

  //you can declare variables or functions only visible to this scope anywhere here
  var randomVar = 'testVar';
  function onlyVisibleHere() { /* doSomething */ }

  //if you want functions visible to outside set them like so 
  nameOfLibrary.nameOfFunction = function() {
    //code to run
  }

  //lastly return your library
  return nameOfLibrary;
}
于 2016-07-22T09:57:05.510 に答える
1

UMD一般的に使用されているものです。

(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    (global.MyLibrary = factory());
}(this, (function () { 'use strict';

  // Private implementation here

  let secret = "message";

  // Whatever is returned is what `global.MyLibrary` will be
  return {
     getSecret: () => secret
  };

})));

console.log(MyLibrary.getSecret()); // "message"
console.log(secret); // Uncaught ReferenceError: secret is not defined

これは、2つの引数ですぐに呼び出されるIIFEです。およびそれぞれthisパラメーターである関数式です。これにより、実装の範囲が非公開になり、名前の衝突が防止されます。globalfactory

スクリプトがブラウザで実行される場合、はにthisなりますwindow。したがって、window.MyLibraryはfactory()、2番目の引数の関数式から返されるものと等しくなります。これはライブラリのAPIです。

于 2017-06-02T15:22:31.803 に答える
0

後者が好ましい。特にライブラリを作成するときは、グローバル名前空間をできるだけ汚染しないようにすることが重要です。コードは、既存のコードにできるだけ干渉しないようにする必要があります。

于 2012-11-28T13:31:02.260 に答える
-1

2番目のアプローチは推奨される方法ですが、新しい名前空間を作成することで改善できます。利点は、発生する可能性のあるすべての名前の衝突を回避できることに加えて、コードをより適切に制御できることです。「MyNamespace」という名前空間を作成し、その中にLibraryクラスを格納します。このように、クラス名が「Library」のファイルが他にある場合でも、名前の衝突は発生しません。

(function($){
    $.Library = function(){
        this.memory = {}; 
        this.doSomething  = function() {};
    };

$.Library.prototype = { //these will be common for all the objects 
    commonFunction : function() {

    },
    function2 : function() {

    }
};

})(MyNameSpace);

以下のコードを使用して、Libraryクラスの新しいオブジェクトをインスタンス化できます。

<script>
var lib = new MyNamespace.Library;
</script>
于 2015-02-24T16:04:51.457 に答える