web-dev-qa-db-ja.com

プロトタイプとクロージャーを使用することで最もよく解決されるプログラミングの一般的な問題は何ですか?

両方の概念を理解している限り、JavaScriptのクロージャーとプロトタイプasideを利用してインスタンス化可能および/またはまたはカプセル化されたクラスのようなブロック(これはアセットよりも回避策のように思えます)

値としての関数や非ブール値の論理評価などの他のJS機能は、恋に落ちるのがはるかに簡単です...

プロポタイプの継承とクロージャーを使用することで最もよく解決されるプログラミングの問題は何ですか?

8
vemv
  1. クロージャは、関数を値として有用なものにするものです。関数を渡すとき、ほぼ確実に何らかのコンテキストを引き継ぐ必要があります。これは、クロージャーが行うこととまったく同じです。

  2. プロトタイプは、クラス継承のより単純なバージョンにすぎません。インスタンスとクラス(動的言語では特別な種類のインスタンスで表されます)ではなく、インスタンスだけがあり、プロトタイプがクラスです(プロトタイプは基本クラスです)。したがって、基本的には同じ問題を解決します。プロトタイプだけを実装する方が簡単で(JavaScriptが選択したのはそのためです)、使用するのがやや難しく(まあ、構文上の砂糖がないだけです)、悪用しやすくなります。

5
Jan Hudec

クロージャーは、それなしでは解決できないプログラミング問題を解決しません。ただし、これはチューリングの完全性に必要のない言語機能でも言えるので、あまり意味がありません。

クロージャーを使用しないように、クロージャーを使用するコードをどのように書き直す必要があるかを考えてください。おそらく、呼び出しの間に状態を保持できるように、クロージャーに追加のプロパティを指定して関数を提供します。これは、すでにスコープ内にある変数を関数の同じ名前のプロパティにコピーするだけなので、画面に「なぜバカなコンパイラーができないのか(通訳、なんでも)これを理解しますか?」それがクロージャです。愚かなコンパイラisそれを理解するのに十分スマートです。

4
psr

クロージャーは非同期ロジックに最適です。

それは主に私のためのコードの編成についてです。コードが何をしているかを分割するためにたくさんのローカル関数を持つことは素晴らしいことです。

_create: function _create(post, cb) {
    // cache the object reference
    var that = this;

    function handleAll(err, data) {
        var rows = data.rows;

        var id = rows.reduce(function(memo, item) {
            var id = +item.id.split(":")[1];
            return id > memo ? id : memo;
        }, 0);
        id++;


        var obj = {
            title: post.title,
            content: post.content,
            id: id,
            // refer to the object through the closure
            _id: that.prefix + id,
            datetime: Date.now(),
            type: "post"
        }

        PostModel.insert(obj, handleInsert);
    }

    // this function doesn't use the closure at all.
    function handleInsert(err, post) {
        PostModel.get(post.id, handleGet);
    }

    // this function references cb and that from the closure
    function handleGet(err, post) {
        cb(null, that.make(post));
    }

    PostModel.all(handleAll);
}
_

これがクロージャーの別の例です

_var cachedRead = (function() {
    // bind cache variable to the readFile function
    var cache = {};

    function readFile(name, cb) {
        // reference cache
        var file = cache[name];
        if (file) {
            return cb(null, file);
        }

        fs.readFile(name, function(err, file) {
            if (file) cache[name] = file;
            cb.apply(this, arguments);
        });
    }

    return readFile;
})();
_

そして別の例

_create: function _create(uri, cb, sync) {
    // close over count
    var count = 3;

    // next only fires cb if called three times
    function next() {
        count--;
        // close over cb
        count === 0 && cb(null);
    }

    // close over cb and next
    function errorHandler(err, func) {
        err ? cb(err) : next();
    }

    // close over cb and next
    function swallowFileDoesNotExist(err, func) {
        if (err && err.message.indexOf("No such file") === -1) {
            return cb(err);
        }
        next();
    }

    this.createJavaScript(uri, swallowFileDoesNotExist, sync)

    this.createDocumentFragment(uri, errorHandler, sync);

    this.createCSS(uri, swallowFileDoesNotExist, sync);
},
_

クロージャーを使用する代わりに、f.bind(null, curriedVariable)を使用して変数を関数にカリー化します。

ただし、一般に、非同期プログラミングロジックはコールバックを使用し、コールバック内の状態の操作はカリー化またはクロージャに依存しています。個人的には閉鎖を好む。

プロトタイプ継承の使用については、OOを許可しますか?プロトタイプの継承は、それが「有用」であると見なされるために、実際にそれ以上のことを行う必要がありますか?それは継承ツールであり、継承を可能にし、それは十分に便利です。

2
Raynos