両方の概念を理解している限り、インスタンス化および/またはカプセル化されたクラスのようなブロックを作成するためにそれらを使用する以外に、JavaScriptのクロージャーとプロトタイプをどのように利用できるのかわかりません(これは私にとってアセットよりも回避策のようです) )
値としての関数や非ブール値の論理評価など、他のJS機能は、恋に落ちるのがはるかに簡単です...
プロポタイプの継承とクロージャを使用することで最もよく解決される一般的なプログラミングの問題は何ですか?
両方の概念を理解している限り、インスタンス化および/またはカプセル化されたクラスのようなブロックを作成するためにそれらを使用する以外に、JavaScriptのクロージャーとプロトタイプをどのように利用できるのかわかりません(これは私にとってアセットよりも回避策のようです) )
値としての関数や非ブール値の論理評価など、他のJS機能は、恋に落ちるのがはるかに簡単です...
プロポタイプの継承とクロージャを使用することで最もよく解決される一般的なプログラミングの問題は何ですか?
回答:
クロージャは、関数を値として有用なものにするものです。関数を渡すとき、ほぼ確実に何らかのコンテキストを引き継ぐ必要があります。これは、クロージャーが行うこととまったく同じです。
プロトタイプは、クラス継承の単純なバージョンにすぎません。インスタンスとクラス(動的言語では特別な種類のインスタンスで表されます)ではなく、インスタンスだけがあり、プロトタイプがクラスです(プロトタイプは基本クラスです)。つまり、基本的には同じ問題を解決します。プロトタイプの方が実装が簡単で(JavaScriptが選択したのはそのためです)、使用するのがやや難しく(まあ、構文上の砂糖がないだけです)、悪用しやすくなります。
void* data
引数を介して関数にコンテキストを渡し、呼び出された関数によってダウンキャストされることがよくあります。
クロージャーは、それなしでは解決できないプログラミング問題を解決しません。ただし、これはチューリングの完全性に必要のない言語機能でも言えるので、あまり意味がありません。
クロージャーを使用しないように、クロージャーを使用するコードをどのように書き直す必要があるかを考えてください。おそらく、関数に呼び出しの間に状態を保持できるように、クロージャーに追加のプロパティを追加します。これは、既にスコープ内にある変数を関数の同じ名前のプロパティにコピーするだけなので、画面に「なぜ愚かなコンパイラ(通訳、なんでも)これを理解しますか?」それがクロージャです。愚かなコンパイラはそれを理解するのに十分スマートです。
クロージャーは非同期ロジックに最適です。
それは主に私のためのコードの編成についてです。コードが何をしているかを分割するためにたくさんのローカル関数を持つことは素晴らしいことです。
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を許可しますか?プロトタイプの継承は、それが「有用」であると見なされるために、実際にそれ以上のことを行う必要がありますか?それは継承ツールであり、継承を可能にし、それは十分に便利です。