これらの構成要素の違い、長所/短所 (もしあれば) は何ですか?
new function(obj) {
console.log(obj);
}(extObj);
対
(function(obj) {
console.log(obj);
})(extObj);
これらの構成要素の違い、長所/短所 (もしあれば) は何ですか?
new function(obj) {
console.log(obj);
}(extObj);
対
(function(obj) {
console.log(obj);
})(extObj);
最初のものは、匿名コンストラクター関数(= this
)の新しく構築されたインスタンスへの参照を返します。
2つ目は、無名関数の戻り値を返します。関数にはreturnステートメントがないため、暗黙的にundefinedを返します。
次のことを試してください。
var t1 = new function(obj) { console.log(obj); }(extObj);
var t2 = (function(obj) { console.log(obj); })(extObj);
typeof t1 => "object"
typeof t2 => "undefined"
(ところで、t1.constructor
作成した元の関数が返されますt1
。)
returnステートメントを追加すると、違いがより明確になります。
var t1 = new function(obj){ return(obj); }("foo");
var t2 = (function(obj){ return(obj); })("bar");
console.log(t1) => "object"
console.log(t2) => "bar"
IMO、これは(function)()
日常のユースケースではるかに便利になります-この関数の実行の戻り値を変数に割り当てます。これは、すぐに呼び出される関数で作業している場合に通常必要なものです。特に(擬似コード)のようなより複雑なものがある場合:
var myNameSpace = (function(){
/* do some private stuff here*/
...
/* expose parts of your anonymous function by returning them */
return{
functionX,
variable1,
variable2
}
}();
基本的に、任意の単項演算子を使用して、関数宣言を式に変換し、すぐに呼び出すことができます。したがって、次のように書くこともできます。
!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();
関数のreturnステートメントに応じて、これらは異なる戻り結果を提供します。-数値(負の符号を適用)が戻り値に適用されるため、戻り値の評価を!
無効にします。+|-
~
bitwise not
this
即時呼び出し関数を明示的に処理することを検討している場合、最初の関数が関数内で外の世界に自動的に戻ることを除いて、2つの間に実際の違いはありません(これが行われますnew
) 。 、デフォルトでは、別の戻り値が指定されていない場合(通常の関数は戻りますundefined
)。
残りの主な違いは実際には重要ではありません-プロトタイプチェーンへのアクセスは無意味になります。無名関数に返さthis.constructor
れたポイントがあると、後で使用するために無名関数をキャッシュするためのアクセスが可能になります(なんとかして囲まれた関数を貼り付けることができた場合は、イベントリスナーからそれを削除します......それ自体がトリックになります)。
返されたthis
オブジェクトのコンストラクタープロパティとしてすぐに呼び出された関数をキャッシュできるようにすることは、セキュリティリスクになる可能性があります......または非常に特定のシナリオで非常に役立つ可能性があります。
コードをインラインで起動するという毎日の目的-実際の違いはありません。
もう 1 つの違いは、最初の呼び出しで追加のオブジェクトが作成されることです。ここでは、オブジェクトを示すために名前f
と名前を付けました。o
var o = new function f(obj) {
console.log(obj);
}(extObj);
2 番目のケースでは、引き続き関数オブジェクトf
を作成しますが、作成しませんo
:
(function f(obj) {
console.log(obj);
})(extObj);
クロージャは引き続き作成されますが、プロトタイプ チェーン全体やその他の属性 (隠しクラス参照など) を保持しないため、実際の JavaScript オブジェクトよりも安価です。