JavaScript関数

範囲

実行環境とスコープ
各関数には独自の実行環境があります。実行フローが関数に入ると、関数の環境が環境スタックにプッシュされ、関数が実行された後、スタックはその環境とコントロールをポップアップします前の実行環境に戻ります。

コードが環境で実行されると、変数オブジェクトのスコープチェーンが作成されます。スコープチェーンの目的は、実行環境がアクセスできるすべての変数と関数に順序正しくアクセスできるようにすることです。スコープチェーンのフロントエンドは常に、現在実行中のコードが配置されている環境の変数オブジェクトです。この環境が関数の場合、そのアクティブオブジェクトは変数オブジェクトとして使用されます。
アクティブなオブジェクトには、最初は1つの変数、引数オブジェクト(このオブジェクトはグローバルな返済には存在しません)、スコープチェーンの次の変数オブジェクトは包含(外部)環境から、次の変数オブジェクトは次は環境が含まれています。このようにして、グローバル実行環境へと続き、グローバル実行環境の変数オブジェクトは常にスコープチェーンの最後のオブジェクトです。

内部環境はスコープチェーンを通じてすべての外部環境にアクセスできますが、外部環境は内部環境の変数や関数にアクセスできません。これらの環境間の関係は直線的で規則的です。各環境はスコープチェーンを上方向に検索して変数と関数名をクエリできますが、スコープチェーンを下方向に検索して別の実行環境に入ることはできません。

関数宣言と関数式

パーサーが実行環境にデータをロードするとき、関数宣言と関数式では同じではありません。パーサーは、最初に関数宣言を読み取り、コードを実行する前にそれを使用可能(アクセス可能)にします。関数式は、パーサーがコードを実行するまで待機してからでなければ、解釈および実行できません。

関数の内部プロパティ

関数内の2つの特別なオブジェクト:引数この
引数は、関数に渡されるすべてのパラメーターを含む配列のようなオブジェクトです。
引数の主な目的は関数パラメーターを保存することですが、このオブジェクトにはcalleeというプロパティもあります。属性は実行であり、argumentsオブジェクトを所有する関数を指しています。
階乗の例:関数の実行は関数名factrialと密に結合され、arguments.calleeを使用した結合を排除します。

function factrial(num){
	if(num <= 1){
		return 1;
	}else{
		return num * factrial(num-1);
	}
}
function factrial(num){
	if(num <= 1){
		return 1;
	}else{
		return num * arguments.callee(num-1);
	}
}
var trueFactorial = factorial;
factorial = function(){
	return 0;
}
alert(trueFactorial(5));//120
alert(factorial(5));//0

このオブジェクト

これは、関数データが​​実行される環境オブジェクトを指します、または言うことができます(関数がWebページのグローバルスコープで呼び出される場合、このオブジェクトはウィンドウを指します)

window.color = "red";
var o = {color:"blue"};
function saycolor(){
	alert(this.color);
}
saycolor();//red
o.saycolor() = saycolor;
o.saycolor();//blue

注意!関数の名前は、ポインタを含む単なる変数です。異なる環境で実行された場合でも、グローバルsaycolor()関数とo.saycolor()は同じ関数を指します

callerは関数オブジェクトのプロパティであり、このプロパティは現在の関数を呼び出す関数を保持します。
このプロパティは現在の関数を呼び出すための参照を保持します。現在の関数がグローバルスコープで呼び出されると、nullを返します

function outer(){
	inner();
}
function inner(){
	alert(inner.caller);
}
outer();

outer()関数のソースコードがポップアップし、outer()がinner()を呼び出すため、inner.callerはouter()を指します。より疎結合を実現するには、arguments.callerを渡します。

function outer(){
	inner();
}
function inner(){
	alert(arguments.callee.caller);
}
outer();

ストリクトモードでは、arguments.calleeにアクセスするとエラーが発生します
。ECMAScriptは、arguments.callerプロパティも定義します。ストリクトモードでは、これも正しくありません。非ストリクトは常に未定義です。このプロパティは、arguments.callerプロパティとfunction callerプロパティを区別するためのものです。
上記の変更は、この言語のセキュリティを強化するためのもので、サードパーティのコードが同じ環境でコードをのぞき見できないようになっています。ストリクトモードでは、関数の呼び出し元属性に値を割り当てることはできません。エラーが報告されます。

関数のプロパティとメソッド
関数はオブジェクトであるため、関数にもプロパティとメソッドがあります
。2つのプロパティ:長さとプロトタイプの長さの
プロパティは、関数が受信する名前付きパラメーターの数を示します

プロトタイプ

ECMAScriptの参照型の場合、prototpyeはすべてのインスタンスメソッドを保存する実際の場所です。toString()やvalueOf()などのメソッドは実際にはプロトタイプ名で格納されますが、それぞれのオブジェクトのインスタンスを介してのみアクセスされます。
プロトタイププロパティは列挙可能ではなく、for-inを使用して見つけることができません。
各関数には、apply()とcall()の2つの非継承メソッドが含まれています。これら2つのメソッドの目的は、特定のスコープで関数を呼び出すことです。これは、実際には関数のスコープを設定することと同等であり、もう1つはパラメーター配列です。

function sum(num1,num2){
	return num1 + num2;
}
function callSum(num1,num2){
	return sum.apply(this,arguments);//sum.apply(this,a[num1,num2]);
}
alert(callSum(10,10));

callSum()は、Sum()関数(グローバルスコープで呼び出されるため、ウィンドウオブジェクトが渡されるため)および引数オブジェクトを実行するときにthisをthis値として渡します。厳密モードでは、環境オブジェクトを指定せずに関数を呼び出すと、この値はウィンドウに変換されず、未定義になります。

call()メソッドは、apply()と同じ効果があります。最初のパラメーターはthis値で、残りのパラメーターは関数に直接渡されます。伝達関数のパラメータは、1つずつ指定する必要があります。

function callSum(num1,num2){
	return sum.call(this,num1,num2);
}
alert(callSum(10,10));//20

Apply、call()は、実行する関数のスコープを拡張するのに非常に便利です。

window.color = "red";
var o = {color:"blue"};
function saycolor(){
	alert(this.color);
}
saycolor();//red

この利点は、オブジェクトがメソッドとのカップリング関係を持つ必要がないことです。

saycolor.call(this);//red
saycolor.call(window);//red
saycolor.call(o);//blue

bind()メソッドは関数のインスタンスを作成し、この値はbind()関数に渡された値にバインドされます。

window.color = "red";
var o = {color:"blue"};
function saycolor(){
	alert(this.color);
}
var objectsayColor = sayclor.bind(0);
objectsayColor(); //blue

saycolor()はbind()を呼び出してオブジェクトoを渡し、objectsayColor()関数を作成します。objectsayColor()関数のthis値はoなので、この関数がグローバルスコープで呼び出されても、「青」が表示されます。

関数式

関数を定義する方法:1つは関数宣言です。2つ目は、関数式の
関数宣言機能です。関数宣言の昇格、コードを実行する前に関数宣言の
関数式を読み取ります。関数を作成し、その関数を変数functionNameに渡します。この場合、好きな関数を作成すると、無名関数と呼ばれます(ラムダ関数)、使用前に割り当てる必要があります
//①これは行わないでください

if(condition){
	function sayHi(){
		alert("Hi");
	}
}else{
	function sayHi(){
		alert('"Yo!');
	}
}

//②これができる

var sayHi;
if(condition){
	sayHi = function(){
		alert("Hi!");
	}
}else{
	sayHi = function(){
		alert("Yo!");
	}
}

①無効な文法に属するJSエンジンはエラーを修正し、適切な状態に変換しようとします。しかし、ブラウザーは、肯定的および誤った慣行を修正しようとすることに一貫性がありません

再帰的

再帰関数は、関数がそれ自体を名前で呼び出すと形成されます
。Argumentsは実行中の関数へのポインタなので、関数への再帰呼び出しを実装するために使用できます

function factorial(num){
	if(num<=1){
		return 1;
	}else{
		return num * arguments.callee(num-1);//arguments.callee代替函数名,可以确保无论怎样调用函数都不会出问题。
	}
}

ストリクトモードでは、スクリプトを介してarguments.calleeにアクセスできません。

var factorial = (function f(num){//使用命名函数表达式
	if(num<=1){
		return 1;
	}else{
		return num * f(num-1);
	}
})
元の記事を公開17件 ・いい ね0 訪問数764

おすすめ

転載: blog.csdn.net/CandiceYu/article/details/89889497