2016-03-27 9 views
0

2つの関数オブジェクト:Javascriptで非キャプチャ関数とクロージャを区別することはできますか?

// toplevel 
var f1 = function(){return k;}; 
var f2 = (function(k){return function(){return k;}})(42); 

が同じソースコードを持っている「関数(){戻りkは;}」が、f1f2代わり閉鎖され、k地球環境で検索された機能でありますローカルkをキャプチャした

f2は閉鎖だと言えますか? typeof"function"です。

例えば、関数のソースコードをデータベースに格納することは、evalで関数を再構築できるので意味があります。代わりにクロージャのソースコードを格納することは、キャプチャされた変数のために動作しません。

+4

なぜクロージャである関数とそうでない関数を区別する必要がありますか? – Quentin

+0

どういう意味ですか? 'f1'と' f2'をまったく同じものとして定義しても、 'f1 === f2 // false'のようになります。 –

+0

@Quentin:データベースに関数のソースを格納するのは意味がありますが、クロージャーを格納することはできません。 – 6502

答えて

1

クロージャはタイプではありません。 Closureは、そのスコープが消えた後であっても、そのスコープ内の変数に関数がアクセスできるようにするものです。これの詳細な説明については、彼があなたに知らないJSをチェックしてください。

2つ目のことは、直ちに呼び出される関数です。関数の周りの()はそれを式にします。評価され、返され、すぐに呼び出されます。

f1がトップレベルのスコープで定義されていますが、f2が直ちに呼び出された関数の内部スコープで定義され、次にトップレベルに戻されるということです。 Closureは、定義されたスコープが破棄された後に、f2にkをアクセスさせるものです。 f2はkに対して閉包を有すると言われる。

要するに、どの範囲の関数が作成されたかを知る方法はありません。

0

f1/f2.prototypeのChromeデバッガを見ると、拡張可能なオブジェクト{}が得られます。内部には、展開可能なコンストラクタもあります。これを展開すると、kとその値を含む<function scope>アイテムが表示されます。

ECMA標準によれば、閉鎖の範囲はinaccessible programaticallyです。

私は、関数がクロージャであるかどうかを判断できる概念コードの証明書を書いて、あなたのサンプル関数に合わせて調整しました。クロージャの異なるタイプの、より複雑なメカニズムを必要とするが、それがうまくいくかもしれない:ncphillipsは言っ

var k=10; 
var f1 = function(){return k;}; 
var f2 = (function(k){return function(){return k;}})(42); 
function isClosure(f) { 
    var testF=new Function('return ('+f.toString()+')();'); 
    return testF()!=f(); 
} 

alert('f1 is '+(isClosure(f1)?'':'not')+' a closure\r\nf2 is '+(isClosure(f2)?'':'not')+' a closure'); 
0

として、閉鎖はJSタイプではありません。これは、動的スコープの問題を解決するためのデータ構造の設計です。 https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scope_vs._dynamic_scope ほとんどの関数型プログラミング言語では、クロージャは開発者にとって透過的です。この構造を訪問したり制御する方法はありません。 vmがクロージャを作成するたびに(通常、関数を宣言するときに起こります)、スコープチェーンを検索し、それらにリンクを張ります(これは私の言葉です。あなたのコードでは:

var f1 = function(){return k;}; 
var f2 = (function(k){return function(){return k;}})(42); 

あなたは、彼らものの両方のリターンkをするにはF1 refと関数f2 refが異なるスコープチェーンを持っている機能を見ることができますが、同じ領域がどのようなkのレフリーではありませんし。 f2またはf1がクロージャであれば、両方とも機能していて、どちらもクロージャを持っていますが、この例では同じクロージャを参照しているわけではありません。

どちらもkを返します。そうすると、「k」を見つけるためにクロージャの内部を(多かれ少なかれスコープチェーンと同じに)見ます。 f1の場合は、このコードでは 'k'を与えなかったので、まだ 'k'がない場合はグローバルになるまでルックアップを維持し、次にundefinedを返します。 f2の場合、function(k){}のスコープはf2の「最低スコープ」で、「k」が見つかったので、それを返します。これが違いです。

閉包作成のキーワードは関数宣言であり、vmが関数を宣言すると、関数に閉包が与えられ、宣言が行われるスコープに依存します。

私の英語は良くありません。あなたのお役に立てば幸いです。

関連する問題