以前はこれが何を意味するのかを知っていましたが、今は苦労しています...
これは基本的に言っていdocument.onload
ますか?
(function () {
})();
以前はこれが何を意味するのかを知っていましたが、今は苦労しています...
これは基本的に言っていdocument.onload
ますか?
(function () {
})();
回答:
これは、即時に呼び出される関数式、または略してIIFEです。作成された直後に実行されます。
これは、任意のイベント(などdocument.onload
)のイベントハンドラーとは関係ありません。
括弧の最初のペア内の部分を検討してください。.... itは正規関数式です。次に、最後のペアを確認します。これは通常、関数を呼び出す式に追加されます。この場合、以前の表現です。(function(){})();
(function(){})();
(他の通常の関数のように)IIFE内で使用されるすべての変数はそのスコープの外からは見えないため、このパターンはグローバル名前空間の汚染を回避しようとするときによく使用されます。
このため、この構造をのイベントハンドラーと混同したのはこのwindow.onload
ためです。
(function(){
// all your code here
var foo = function() {};
window.onload = foo;
// ...
})();
// foo is unreachable here (it’s undefined)
関数は、解析された後ではなく、作成された直後に実行されます。スクリプトブロック全体は、コードが実行される前に解析されます。また、コードの解析は、コードが実行されることを自動的に意味するわけではありません。たとえば、IIFEが関数内にある場合、関数が呼び出されるまでコードは実行されません。
更新 これはかなり人気のあるトピックであるため、IIFEはES6の矢印関数を使用して作成することもできます(Gajusがコメントで指摘したように)。
((foo) => {
// do something with foo here foo
})('foo value')
function(){ var foo = '5'; }
これは、作成された直後に実行される匿名関数です。
変数に割り当ててすぐに使用した場合と同じように、変数はありません。
var f = function () {
};
f();
jQueryには、あなたが考えているかもしれない同様の構成があります:
$(function(){
});
これは、ready
イベントをバインドする短い形式です。
$(document).ready(function(){
});
しかし、上記の2つの構成はIIFEではありません。
すぐに呼び出される関数式(IIFE)は、すぐに関数を呼び出します。これは単に、定義が完了した直後に関数が実行されることを意味します。
さらに3つの一般的な表現:
// Crockford's preference - parens on the inside
(function() {
console.log('Welcome to the Internet. Please follow me.');
}());
//The OPs example, parentheses on the outside
(function() {
console.log('Welcome to the Internet. Please follow me.');
})();
//Using the exclamation mark operator
//https://stackoverflow.com/a/5654929/1175496
!function() {
console.log('Welcome to the Internet. Please follow me.');
}();
戻り値に特別な要件がない場合は、次のように記述できます。
!function(){}(); // => true
~function(){}(); // => -1
+function(){}(); // => NaN
-function(){}(); // => NaN
または、次のようにすることもできます。
~(function(){})();
void function(){}();
true && function(){ /* code */ }();
15.0, function(){ /* code */ }();
あなたも書くことができます:
new function(){ /* code */ }
31.new function(){ /* code */ }() //If no parameters, the last () is not required
31.new
「無効な構文です
;(function(){}());
つまり、すぐに実行します。
だから私がするなら:
var val = (function(){
var a = 0; // in the scope of this function
return function(x){
a += x;
return a;
};
})();
alert(val(10)); //10
alert(val(11)); //21
フィドル:http : //jsfiddle.net/maniator/LqvpQ/
var val = (function(){
return 13 + 5;
})();
alert(val); //18
その構造は、即時に呼び出される関数式(IIFE)と呼ばれ、即座に実行されます。インタプリタがその関数に到達したときに自動的に呼び出される関数と考えてください。
最も一般的なユースケース:
最も一般的な使用例の1つは、を介して作成される変数のスコープを制限することですvar
。で作成された変数のvar
スコープは関数に限定されているため、この構成(特定のコードの関数ラッパー)は、変数のスコープがその関数からリークしないようにします。
次の例でcount
は、はすぐに呼び出される関数の外では使用できません。つまり、スコープはcount
関数からリークしません。ReferenceError
とにかくすぐに呼び出された関数の外でアクセスしようとすると、を取得するはずです。
(function () {
var count = 10;
})();
console.log(count); // Reference Error: count is not defined
ES6代替(推奨)
ES6では、およびを使用して変数を作成できるようにlet
なりましたconst
。どちらもブロックスコープです(var
関数スコープとは異なります)。
したがって、前述のユースケースにIIFEの複雑な構成を使用する代わりに、はるかに単純なコードを記述して、変数のスコープが目的のブロックからリークしないようにすることができます。
{
let count = 10;
}
console.log(count); // ReferenceError: count is not defined
この例では、コードのブロックに限定let
するcount
変数を定義するために使用count
し、中括弧で作成しました{...}
。
私はそれを「カーリー刑務所」と呼びます。
(function () {
})();
これはIIFE(Immediately Invoked Function Expression)と呼ばれます。有名なJavaScriptデザインパターンの1つであり、現代のモジュールパターンの心臓部です。名前が示すように、作成された直後に実行されます。このパターンは、分離された、またはプライベートな実行範囲を作成します。
ECMAScript 6より前のJavaScriptは字句スコープを使用していたため、ブロックスコープのシミュレーションにIIFEが使用されました。(ECMAScript 6を使用するlet
と、およびconst
キーワードの導入によりブロックスコープが可能になります。)
字句スコープに関する問題のリファレンス
生命維持のを使用した場合のパフォーマンス上の利点は次のように一般的に使用されるグローバルオブジェクトを渡す機能であるwindow
、document
スコープのルックアップを減らすことによって、引数として、など。(JavaScriptはローカルスコープでプロパティを検索し、グローバルスコープまでチェーンを上っていくことを思い出してください)。したがって、ローカルスコープのグローバルオブジェクトにアクセスすると、以下のようにルックアップ時間が短縮されます。
(function (globalObj) {
//Access the globalObj
})(window);
いいえ、この構成は名前付けのスコープを作成するだけです。あなたがそれを部分的に壊すならば、あなたはあなたが外部を持っていることがわかります
(...)();
それが関数呼び出しです。括弧内には次のものが含まれます。
function() {}
それは無名関数です。構造内でvarを使用して宣言されたものはすべて、同じ構造内でのみ表示され、グローバル名前空間を汚染しません。
これは、Javascriptですぐに呼び出される関数式です。
JSでIIFEを理解するために、それを分解してみましょう。
a = 10 output = 10 (1+3) output = 4
// Function Expression var greet = function(name){ return 'Namaste' + ' ' + name; } greet('Santosh');
関数式のしくみ:
-JSエンジンが初めて実行されるとき(実行コンテキスト-フェーズの作成)、この関数(=の右側)は実行されず、メモリに保存されません。変数「greet」には、JSエンジンによって「未定義」の値が割り当てられます。
-実行中(実行コンテキスト-実行フェーズ)、機能オブジェクトはその場で作成され(まだ実行されていません)、「greet」変数に割り当てられ、「greet( 'somename')」を使用して呼び出すことができます。
3.すぐに呼び出される関数式:
例:
// IIFE
var greeting = function(name) {
return 'Namaste' + ' ' + name;
}('Santosh')
console.log(greeting) // Namaste Santosh.
IIFEの仕組み:
-関数宣言の直後の「()」に注意してください。すべてのfuntionオブジェクトには、呼び出し可能な「CODE」プロパティがアタッチされています。そして、 '()'括弧を使用してそれを呼び出す(または呼び出す)ことができます。
-したがって、ここでは、実行(実行コンテキスト-実行フェーズ)中に、関数オブジェクトが作成され、同時に実行され
ます。つまり、関数オブジェクトではなく、あいさつ変数に戻り値(文字列)があります。
JSでのIIFEの典型的な使用例:
次のIIFEパターンは非常に一般的に使用されます。
// IIFE
// Spelling of Function was not correct , result into error
(function (name) {
var greeting = 'Namaste';
console.log(greeting + ' ' + name);
})('Santosh');
したがって、この関数は同時に作成されて実行されます(IIFE)。
IIFEの重要なユースケース:
IIFEはコードを安全に保ちます。
-関数であるIIFEには独自の実行コンテキストがあります。つまり、その内部で作成されたすべての変数はこの関数に対してローカルであり、グローバル実行コンテキストと共有されません。
アプリケーションでiife.jsと一緒に使用されている別のJSファイル(test1.js)があるとします(以下を参照)。
// test1.js
var greeting = 'Hello';
// iife.js
// Spelling of Function was not correct , result into error
(function (name) {
var greeting = 'Namaste';
console.log(greeting + ' ' + name);
})('Santosh');
console.log(greeting) // No collision happens here. It prints 'Hello'.
したがって、IIFEは、意図せずにグローバルオブジェクトと衝突しない安全なコードを作成するのに役立ちます。
これは、自己呼び出し型の無名関数です。
W3Schoolsによる自己呼び出し関数の説明を確認してください。
関数式は「自己呼び出し」にすることができます。
自己呼び出し式は、呼び出されることなく、自動的に呼び出されます(開始されます)。
関数式は、式の後に()が続く場合、自動的に実行されます。
関数宣言を自分で呼び出すことはできません。
(function named(){console.log("Hello");}());
<-自己実行の名前付き関数
これは、自己呼び出しの無名関数です。定義中に実行されます。つまり、この関数が定義され、定義の直後に呼び出されます。
構文の説明は次のとおりです。最初の()
括弧内の関数は名前のない関数であり、次の();
括弧によって、定義時に呼び出されていることがわかります。そして()
、最初の括弧内にある関数で取得されるこの2番目の括弧内の引数を渡すことができます。この例を見てください:
(function(obj){
// Do something with this obj
})(object);
ここで、渡した「オブジェクト」は、関数シグネチャで取得しているため、「obj」によって関数内でアクセスできます。
ここから始める:
var b = 'bee';
console.log(b); // global
関数に入れると、もはやグローバルではなくなります-あなたの第一の目標です。
function a() {
var b = 'bee';
console.log(b);
}
a();
console.log(b); // ReferenceError: b is not defined -- *as desired*
関数をすぐに呼び出します-おっと:
function a() {
var b = 'bee';
console.log(b);
}(); // SyntaxError: Expected () to start arrow function, but got ';' instead of '=>'
括弧を使用して、構文エラーを回避します。
(function a() {
var b = 'bee';
console.log(b);
})(); // OK now
関数名は省略できます。
(function () { // no name required
var b = 'bee';
console.log(b);
})();
それ以上複雑にする必要はありません。
Uncaught SyntaxError: Unexpected token )
矢印関数についての説明ではなく、実際に取得します。アロー関数のエラーをスローすることで、フィドルを共有できますか?
自己実行匿名関数。作成されるとすぐに実行されます。
これが役立つ短いダミーの例は次のとおりです。
function prepareList(el){
var list = (function(){
var l = [];
for(var i = 0; i < 9; i++){
l.push(i);
}
return l;
})();
return function (el){
for(var i = 0, l = list.length; i < l; i++){
if(list[i] == el) return list[i];
}
return null;
};
}
var search = prepareList();
search(2);
search(3);
そのため、毎回リストを作成する代わりに、1回だけ作成します(オーバーヘッドが少ない)。
自己実行機能は通常、コンテキストをカプセル化し、名前の共謀を回避するために使用されます。(function(){..})()内で定義する変数はグローバルではありません。
コード
var same_name = 1;
var myVar = (function() {
var same_name = 2;
console.log(same_name);
})();
console.log(same_name);
この出力を生成します:
2
1
この構文を使用することで、JavaScriptコードの他の場所で宣言されたグローバル変数との衝突を回避できます。
var same_name = 1; var myVar = function() { var same_name = 2; console.log(same_name); }; myVar(); console.log(same_name);
同じ結果になります。
これはIIFE-即時に呼び出される関数式と呼ばれます。構文と使用法を示す例を次に示します。変数の使用範囲を関数までに限定し、それ以降は使用しません。
(function () {
function Question(q,a,c) {
this.q = q;
this.a = a;
this.c = c;
}
Question.prototype.displayQuestion = function() {
console.log(this.q);
for (var i = 0; i < this.a.length; i++) {
console.log(i+": "+this.a[i]);
}
}
Question.prototype.checkAnswer = function(ans) {
if (ans===this.c) {
console.log("correct");
} else {
console.log("incorrect");
}
}
var q1 = new Question('Is Javascript the coolest?', ['yes', 'no'], 0);
var q2 = new Question('Is python better than Javascript?', ['yes', 'no', 'both are same'], 2);
var q3 = new Question('Is Javascript the worst?', ['yes', 'no'], 1);
var questions = [q1, q2, q3];
var n = Math.floor(Math.random() * questions.length)
var answer = parseInt(prompt(questions[n].displayQuestion()));
questions[n].checkAnswer(answer);
})();
IIFE(即時に呼び出される関数式)は、スクリプトがロードされてすぐに実行される関数です。
iife.jsという名前のファイルに記述された以下の関数を考えます。
(function(){
console.log("Hello Stackoverflow!");
})();
上記のコードは、iife.jsをロードするとすぐに実行され、 ' Hello Stackoverflow!「開発者ツール」コンソール。
詳細な説明については、即時に呼び出される関数式(IIFE)を参照してください。
もう1つの使用例は、キャッシュオブジェクトがグローバルではないメモ化です。
var calculate = (function() {
var cache = {};
return function(a) {
if (cache[a]) {
return cache[a];
} else {
// Calculate heavy operation
cache[a] = heavyOperation(a);
return cache[a];
}
}
})();
即時に呼び出される関数式(IIFE)は、作成されるとすぐに実行される関数です。イベントや非同期実行とは関係ありません。以下に示すように、IIFEを定義できます。
(function() {
// all your code here
// ...
})();
括弧の最初のペアfunction(){...}は、括弧内のコードを式に変換します。括弧の2番目のペアは、式から生成された関数を呼び出します。
IIFE
は、自己呼び出しの無名関数として説明することもできます。その最も一般的な使用法は、varを介して作成される変数のスコープを制限するか、名前の衝突を回避するためにコンテキストをカプセル化することです。
自己喚起匿名関数が使用される理由は、(関数と変数にスコープを与えることに加えて)呼び出されることになるコードを「セットアップ」するため、他のコードによって呼び出されないようにするためです。
つまり、これらはプログラムの最初に「クラスを作成する」プログラムのようなものです。それらが(自動的に)インスタンス化された後、使用できる関数は、無名関数から返されるものだけです。ただし、その他のすべての '非表示の関数は、状態(スコープの作成中に設定された変数)とともに、まだ存在しています。
とてもかっこいい。
次のコード:
(function () {
})();
即時呼び出し関数式(IIFE)と呼ばれます。
これは( yourcode )
、JavaScript の演算子が式を強制するため、関数式と呼ばれます。関数式と関数宣言の違いは次のとおりです。
// declaration:
function declaredFunction () {}
// expressions:
// storing function into variable
const expressedFunction = function () {}
// Using () operator, which transforms the function into an expression
(function () {})
式は、単一の値に評価できる一連のコードです。上記の例の式の場合、この値は単一の関数オブジェクトでした。
関数オブジェクトに評価される式を作成したら、()
演算子を使用して関数オブジェクトをすぐに呼び出すことができます。例えば:
(function() {
const foo = 10; // all variables inside here are scoped to the function block
console.log(foo);
})();
console.log(foo); // referenceError foo is scoped to the IIFE
大きなコードベースを処理しているときや、さまざまなライブラリをインポートしているときは、名前が競合する可能性が高くなります。IIFE内で関連する(したがって、同じ変数を使用している)コードの特定の部分を記述する場合、すべての変数と関数名はIIFEの関数ブラケットにスコープされます。これにより、名前が競合する可能性が減り、不注意な名前を付けることができます(たとえば、プレフィックスを付ける必要がない)。
これは、これを使用する理由のより詳細な説明です。
「IIFEを使用する主な理由は、データのプライバシーを確保することです。JavaScriptのvarは変数をそれらの包含関数にスコープ指定するため、IIFE内で宣言された変数には外部からアクセスできません。」
これは関数式であり、Immediately Invoked Function Expression(IIFE)の略です。IIFEは、作成された直後に実行される関数です。したがって、関数が呼び出されて実行されるまで待機する必要がある関数ではなく、IIFEはすぐに実行されます。例としてIIFEを作成してみましょう。2つの整数を引数として取り、合計を返すadd関数があるとします。これにより、add関数をIIFEにできます。
ステップ1:関数を定義する
function add (a, b){
return a+b;
}
add(5,5);
ステップ2:関数宣言全体を括弧で囲んで関数を呼び出す
(function add (a, b){
return a+b;
})
//add(5,5);
ステップ3:関数をすぐに呼び出すには、呼び出しから「追加」テキストを削除します。
(function add (a, b){
return a+b;
})(5,5);
IFFEを使用する主な理由は、関数内でプライベートスコープを保持するためです。確認したいJavaScriptコードの中で、グローバル変数をオーバーライドしていないことを確認してください。グローバル変数をオーバーライドする変数を誤って定義することがあります。例で試してみましょう。iffe.htmlというhtmlファイルがあり、bodyタグ内のコードが
<body>
<div id = 'demo'></div>
<script>
document.getElementById("demo").innerHTML = "Hello JavaScript!";
</script>
</body>
さて、上記のコードは何の質問もなく実行されます。今度は、ドキュメントという変数を誤ってまたは意図的にクリアしたと仮定します。
<body>
<div id = 'demo'></div>
<script>
document.getElementById("demo").innerHTML = "Hello JavaScript!";
const document = "hi there";
console.log(document);
</script>
</body>
あなたはにendupうにSyntaxError:非設定可能なグローバルプロパティ文書の再宣言を。
ただし、変数名のドキュメントをクリアしたい場合は、IFFEを使用してクリアできます。
<body>
<div id = 'demo'></div>
<script>
(function(){
const document = "hi there";
this.document.getElementById("demo").innerHTML = "Hello JavaScript!";
console.log(document);
})();
document.getElementById("demo").innerHTML = "Hello JavaScript!";
</script>
</body>
出力:
別の例で試してみましょう。次のような電卓オブジェクトがあるとします。
<body>
<script>
var calculator = {
add:function(a,b){
return a+b;
},
mul:function(a,b){
return a*b;
}
}
console.log(calculator.add(5,10));
</script>
</body>
まあそれは魅力のように機能しています。もし誤って電卓オブジェクトの値を割り当て直したらどうなるでしょうか。
<body>
<script>
var calculator = {
add:function(a,b){
return a+b;
},
mul:function(a,b){
return a*b;
}
}
console.log(calculator.add(5,10));
calculator = "scientific calculator";
console.log(calculator.mul(5,5));
</script>
</body>
はい、あなたはTypeErrorで終わるでしょう:calculator.mulは関数iffe.htmlではありません
しかし、IFFEの助けを借りて、別の変数名計算機を作成して使用できるプライベートスコープを作成できます。
<body>
<script>
var calculator = {
add:function(a,b){
return a+b;
},
mul:function(a,b){
return a*b;
}
}
var cal = (function(){
var calculator = {
sub:function(a,b){
return a-b;
},
div:function(a,b){
return a/b;
}
}
console.log(this.calculator.mul(5,10));
console.log(calculator.sub(10,5));
return calculator;
})();
console.log(calculator.add(5,10));
console.log(cal.div(10,5));
</script>
</body>
ブラケットの2つのセットは少し混乱するように思いますが、Googleの例で別の使用法を見ました。それらは同様の何かを使用しました。これが理解を深めるのに役立つことを願っています。
var app = window.app || (window.app = {});
console.log(app);
console.log(window.app);
したがって、windows.app
が定義されていない場合は、window.app = {}
すぐに実行され、条件の評価中にwindow.app
が割り当てられる{}
ため、結果は両方でapp
ありwindow.app
、になる{}
ため、コンソール出力は次のようになります。
Object {}
Object {}
通常、JavaScriptコードはアプリケーション内でグローバルスコープを持っています。その中でグローバル変数を宣言すると、他の目的のために、開発の他の領域で同じ重複変数を使用する可能性があります。この重複により、エラーが発生する可能性があります。そのため、関数式を直接呼び出すことでこのグローバル変数を回避できます。この式は自己実行式です。このIIFE式内のコードを作成すると、グローバル変数はローカルスコープとローカル変数のようになります。
IIFEを作成する2つの方法
(function () {
"use strict";
var app = angular.module("myModule", []);
}());
または
(function () {
"use strict";
var app = angular.module("myModule", []);
})();
上記のコードスニペットでは、「var app」がローカル変数になりました。