この記事では主に JavaScript 関数式の詳しい説明と例を紹介しますので、必要な方は参考にしてください
JavaScript 関数式
1. 順序
関数を定義するには 2 つの方法があります。は関数宣言、もう 1 つは関数式です。
1.1 関数宣言
function functionName(arg){ //函数体 }
関数宣言について、重要な機能は関数宣言のホイスティングです。これは、コード ステートメントを実行する前に関数が読み取られることを意味します。これは、関数を呼び出すステートメントの後に関数を配置できることを意味します。以下に示すように:
helloworld(); //在代码执行之前会先读取函数声明 function helloworld(){ console.log("hello world"); }
1.2 関数式
var functionName=function(arg){ //函数体 }
この形式は、通常の変数代入ステートメントのように見えます。つまり、関数を作成して変数 functionName に代入します。この場合に作成される関数を無名関数と呼びます。 function キーワードの後に識別子がないためです。
関数式は、他の式と同様に、使用する前に値を割り当てる必要があります。次のコードではエラーが発生します。関数式を使用すると、関数式に値を動的に割り当てることができます。次のコード:
helloworld(); //错误,还未赋值,函数不存在 var helloworld=function(){ console.log("hello world"); }
再帰関数は、関数がそれ自体を名前で呼び出すときに形成されます (C# や他の言語と同じなので、プログラムの中心的な考え方は次のとおりです)似ていますが、文法にはいくつかの違いがあります。1 つの言語の基本をよく学べば、他の言語を学ぶのがはるかに簡単になります。一連の数字のルールは次のとおりです。 1, 2, 3, 5, 8, 13, 21 , 34... 30 番目の桁を検索し、再帰アルゴリズムを使用します。コードは次のとおりです:
var helloworld; //声明
if(condition){ //条件
helloworld=function(){ //赋值
console.log("hello world");
}
}
else{
helloworld=function(){ //赋值
console.log("你好,世界");
}
}
この関数には問題がないように見えますが、次のコードは問題を引き起こす可能性があります:
function foo(n) { if (n <= 0) return 0; else if (n > 0 && n <= 2) return 1; else return foo(n - 1) + foo(n - 2); }
上記のコードは、最初に foo() 関数を変数 foo1 に保存し、次に foo 変数を null に設定します。その結果、への参照は 1 つだけになります。本来の機能。しかし、次に foo1() を呼び出すと、foo() を実行する必要があり、foo はすでに null であるため、エラーが発生します。この場合、arguments.callee を使用すると、この問題を解決できます。 argument.callee は実行される関数へのポインターなので、これを使用して関数への再帰呼び出しを実装できます
var foo1 = foo; foo = null; console.log(foo1(34));
また、名前付き関数式を使用して同じ結果を達成することもできます。例:
function foo(n) { if (n <= 0) return 0; else if (n > 0 && n <= 2) return 1; else return arguments.callee(n - 1) + arguments.callee(n - 2); }
3.1 クロージャは、別の関数のスコープ内の変数にアクセスできる関数を指します。クロージャを作成する一般的な方法は、関数内に別の関数を作成することです。 。 機能。クロージャを理解するには、まず JavaScript の特殊変数のスコープを理解する必要があります。変数のスコープは、グローバル変数とローカル変数の 2 種類にすぎません。次に、それを直感的に表現するためにいくつかのデモを作成します。
グローバル変数は関数内で直接読み取ることができます。変数は関数の外で直接読み取ることはできません:
var foo = (function f(n) { if (n <= 0) return 0; else if (n > 0 && n <= 2) return 1; else return f(n - 1) + f(n - 2); });
ここで注意すべき点は、関数内で変数を宣言するときは var を使用する必要があり、使用しない場合はグローバル変数になります:
。var n = 100; //定义一个全局变量 function fn() { console.log(n); //函数内部直接读取全局变量 } fn();
はい 場合によっては、関数内で宣言された変数を取得する必要があるため、上記のクロージャを作成する一般的な方法を使用して、関数内に別の関数を作成できます:
function fn() { var n = 100; } console.log(n); //n is not defined
上記のコード、関数 fn1 が含まれています 関数 fn 内には、fm 内のすべてのローカル変数が fn1 に表示されます。ただし、その逆は機能しません。fn1 内のローカル変数は fn には見えません。これは、JavaScript 言語の独自の「チェーン スコープ」構造で、子オブジェクトはすべての親オブジェクトの変数をレベルごとに検索します。したがって、親オブジェクトのすべての変数は子オブジェクトから見えますが、その逆はありません。
fn1 は fn の内部変数を読み取ることができることがわかり、fn1 が戻り値として使用されている限り、fn の変数を外部から読み取ることができます
function fn() { n = 100; } fn(); console.log(n); //100
ここで、fn1 はクロージャであり、クロージャは、他の関数内の変数を読み取る関数です。 Javascript言語ではローカル変数を読み込めるのは関数内のサブ関数のみであるため、クロージャは単純に「関数内で定義された関数」として理解できます。したがって、本質的に、クロージャは関数の内部と関数の外部を接続する橋です。
3.2 クロージャの目的
クロージャには 2 つの大きな用途があります。1 つは前述のように関数内の変数を読み取ること、もう 1 つはこれらの変数の値をメモリに保持することです。次のコードに示すように:
function fn() { n = 100; function fn1() { console.log(n); } fn1(); } fn(); //100
注意:由于闭包函数会携带包含它的函数的作用域,因此会比其他函数占用更多的内存,过度使用闭包可能会导致内存占用过多,所以在退出函数之前,将不使用的局部变量全部删除。
四、块级作用域
块级作用域(又称为私有作用域)的匿名函数的语法如下所示:
(function(){ //块级作用域 })();
无论在什么地方,只要临时需要一些变量,就可以使用私有作用域,比如:
(function () { var now = new Date(); if (now.getMonth() == 0 && now.getDate() == 1) { alert("新年快乐"); } })();
把上面这段代码放到全局作用域中,如果到了1月1日就会弹出“新年快乐”的祝福;这种技术经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数。一般来说,我们都应该尽量少向全局作用域中添加变量和函数。在一个由很多开发人员共同参与的大型应用程序中,过多的全局变量和函数很容易导致命名冲突。而通过创建私用作用域,每个开发人员既可以使用自己的变量,又不必担心搞乱全局作用域。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
以上がJavaScript 関数式 (グラフィック チュートリアル)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。