ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript 関数とscope_javascript スキルの概要
js で関数を使用する場合は、次の 3 つの点に注意してください。
1. 関数が呼び出されるとき、関数は宣言されたときの構文環境で実行されます。
2. 関数は、それ自体では実行できません。関数の実行時に、オブジェクトが明示的に指定されていない場合、関数本体内の this ポインターは、その関数を呼び出すオブジェクトを指します。関数を呼び出すと、これはデフォルトでウィンドウを指します (厳密モードを除く。この記事では厳密モードについては説明しません)。
3. 関数は、実行可能コードを含むオブジェクト型データです。
1. 関数 を宣言します。
1. 関数キーワードを使用します
}
var myfun = function(a,b){ return a b;}
3. 関数コンストラクターを使用します。 Function //最初の文字が大文字であることに注意してください
関数は、js に組み込まれた関数であり、すべての関数オブジェクトのコンストラクターです。 (他のデータ オブジェクトにも、Number、Object などの独自の組み込みコンストラクターがあります。これらのコンストラクターのコンストラクターはすべて関数であるため、Function です)。
var myfun = new Function('a,b','return a b;'); 最後のパラメータは関数の本体であり、前のパラメータは文字列であるため、数値は可変です。パラメータを渡して構築します。この記述方法は、関数が長く、めったに使用されない場合には、eval 関数を置き換えるために使用することになるでしょう。
グローバル変数とグローバル関数は両方ともウィンドウ オブジェクトの属性とみなすことができることに注意してください。同じ名前の関数と変数が存在する場合、有効になるのは 1 つだけです (実際には属性は 1 つだけです)。次のコード。
var a=1;
alert(window.a);
関数と変数の宣言はコード解析中に行われますが、解析中には変数が宣言されるだけで、値が割り当てられないという点が異なります。したがって、同じスコープ内に同じ名前の関数と変数が存在する場合、コード実行時に変数が代入される前に同じ名前の関数が有効になります。 window オブジェクト属性の値は新しいデータで上書きされます)、変数は有効になります (ただし、Firefox では、疑似クロージャ内で宣言された関数は宣言後にのみ呼び出すことができます。つまり、事前の呼び出しはありません)。 Firefox の関数の宣言)。
アラート(1);
}
alert(func1); // ポップアップ func1(){alert(2);}
func1(){ //これは、この関数の対象となる、最後に宣言された func1 です
アラート(2);
}
alert(func1); // ポップアップ func1(){alert(2);}
var func1 = function(){ //これは変数の割り当てであり、関数の宣言ではないことに注意してください
アラート(3);
}
alert(func1); //ポップアップ function(){alert(3);}
IE8 および以下のブラウザを除き、式内の関数宣言は匿名関数を返します。名前付き関数を正常に宣言できません
}
(関数 fun(){ });
alert(fun); //error ただし、IE8 でも、式内の名前付き関数は同じ名前の変数をオーバーライドできません:
var fun = 1; //この変数は関数式内の関数名で上書きできません
var f = function fun(){};
alert(f); { };
alert(fun); //1
if(fun = function (){}){
alter(fun) // OK、ここで変数が宣言され、匿名関数が格納されます
}
js 関数は参照オブジェクトです
var a = function(){};
var b=a;
b.x=2;
alert(a.x); //2
2. 関数パラメータ
js関数は、関数を呼び出すときに渡されるパラメータの数が、一般に、js関数を呼び出すときに受け取ることができる仮パラメータの数と一致しているかどうかをチェックしません。もちろん、ブラウジングが異なるとプロセッサも異なる可能性があり、ECMAScript 標準はこれを規制していません。
関数を呼び出すときに渡されるパラメーターの数がわからない場合は、関数の引数オブジェクトを使用できます。
arguments は配列に少し似ており、arguments.length は渡されるパラメータの数、arguments[0] は最初のパラメータ、arguments[1] は 2 番目のパラメータ、というようになります...
関数オブジェクトの長さ属性: この属性はめったに使用されず、関数の長さ属性が関数定義時の仮パラメーターの数であることさえ知っている人はほとんどいません。
alert(arguments.length); //呼び出しをポップアップするときに渡されるパラメータの実際の数
alert(arguments[0]); // 対応するパラメータ a
b を返します;
}
alert(myfun.length); //仮パラメータの数、2
注: 仮パラメータと同じ名前のサブ関数が関数内で宣言されている場合 (同じスコープ内で、変数に値が割り当てられていないときに同じ名前の関数が有効になります)、対応する引数の値ただし、同じ名前がスコープ内で var を使用して宣言されている場合、変数によって引数のパラメータ値が関数によって置き換えられることはありません (ただし、Firefox は置き換えます)。
関数(関数含む)の戻り値としては全てのデータ型が使用可能であり、js関数は戻り値を持たないことも可能です。
4. 関数呼び出し 関数自体は実行されません。関数が実行されるときは、それを呼び出すオブジェクトが常に存在します。
デフォルトでは、どの構文環境でも、関数の呼び出しオブジェクトが明示的に指定されていない場合、関数は window オブジェクトを通じて呼び出されます。このとき、関数本体内の this ポインターは window オブジェクトを指します。
b を返します;
}
myfun(1,2); // 関数を呼び出し、仮パラメータ a と b にそれぞれ対応する 2 つのパラメータを渡します。関数を呼び出すときに、渡されるパラメータの数が仮パラメータを超える場合、のみ使用できます。引数は添え字付きで受け取ります。
関数を呼び出すオブジェクトが明示的に指定されていないため、alert(this) は window オブジェクトをポップアップします。この呼び出し方法が最も一般的です。
関数を明示的に指定するための 3 つの呼び出しオブジェクト メソッドがあります:
1. オブジェクトの属性値として関数が割り当てられている場合、その関数はオブジェクトを介してのみアクセスできます (ただし、関数を呼び出す方法はオブジェクトからのみであるという意味ではありません)。オブジェクトを介した関数は、オブジェクト指向プログラミング言語のメソッドとして呼び出されるのと似ています (実際、js では name メソッドを使用することも一般的です)。
obj.fun=function(a,b){
alert(this); // このポインタをポップします
b を返します;
} //オブジェクトの属性値は関数
alert(obj.fun);// fun 関数にアクセスします。 この関数には、このオブジェクトを介してのみアクセスできます
obj.fun(1,2); //obj オブジェクトを通じて fun 関数を呼び出すと、obj オブジェクトがポップアップします。このメソッドは、obj オブジェクトの fun メソッドの呼び出しとも呼ばれます。
アラート(これ);
b を返します;
}
var obj={};
fun.call(obj,1,2); //obj オブジェクトを通じて fun 関数を呼び出し、ポップアップ ポインターは obj オブジェクトです。
var obj2={};
obj2.fun2 = function(a,b){ //obj2 オブジェクトの属性 fun2 は関数です
アラート(これ);
b を返します;
};
obj2.fun2.call(obj,1,2); //obj オブジェクトを介して、obj2 オブジェクトの fun2 属性値に格納されている関数を呼び出します。このポインタは obj オブジェクトです。
//比較的隠されたメソッド呼び出し: 配列は関数を呼び出します [9, function(){ alter(this[0]) }][1]();//ウィンドウ オブジェクトを使用して関数を呼び出す次のメソッドは同等です
fun(1,2);
window.fun(1,2) //fun 関数がグローバル関数の場合fun.call(window,1,2);
fun.call(this,1,2); //このコードがグローバル環境内 (またはウィンドウ オブジェクトによって呼び出される関数本体内) にある場合、この構文の This 環境では window オブジェクトを指します。
func.call(); //関数がパラメータを渡す必要がない場合
func.call(null,1,2);
func.call(unknown,1,2);var name = "window ";
function kkk(){
console.log(this.name) // ie
}
kkk(); //window
kkk.call( kkk); //kkk 関数が単独で呼び出されました
もう 1 つの見落としやすいエラーは、オブジェクト A のメソッドでオブジェクト B を使用したメソッド呼び出しが実行され、試行が行われることです。オブジェクト B のメソッドを使用します。これは、さまざまなコールバック関数で一般的な、オブジェクト A にアクセスするために使用されます。最も一般的な状況は、ajax コールバック関数での使用です。
$.post(url,{param:"token"},function(dataBack){
host.data = dataBack;
3. メソッド呼び出しを適用します:
apply メソッドと call メソッドの唯一の違いは、関数パラメータを渡す方法です。
obj2.fun2.call(obj,1,2); 適用メソッドを obj2.fun2.apply(obj,[1,2]);
に変更します。apply は、配列のようなメソッドを使用してパラメータを渡すこともできます。配列に加えて、引数と HTMLCollection を使用してパラメータを渡すこともできます。ただし、次のような引数は配列ではありません。
var obj={};関数 fun_1(x,y){
関数 fun_2(a,b){
b を返します;
}
fun_2.apply(obj,arguments); //fun_1 の引数オブジェクトを使用してパラメータを渡します。実際には x、y を受け取ります
} IE8 および IE8 より前のブラウザでパラメータを適用すると 2 つの問題があります
call および apply 呼び出しでは、スカラー データ (true/false、文字列、数値) が渡されると、関数は実行時に渡された基本データをオブジェクトにラップし、これをラップされたオブジェクトを指します。試してください 以下のコードを試してください。
関数 a(){
アラート(this.constructor);
アラート(これ);
}
a.call(false);
a.call(100);
a.call('hello');
この機能を使用してパラメータを渡すこともできますが、この使用法はお勧めできません:
function a(){alert(1 this) } //オブジェクトは操作中に自動的に型変換を実行します
a.call(100); //101
4. オブジェクトコンストラクターとしての関数
関数が new オペレーションをオブジェクト コンストラクターとして使用する場合、this は新しく構築されたオブジェクトを指します。コンストラクターの戻り値が null 以外のオブジェクトでない場合、コンストラクターは実行後に this が指すオブジェクトを返します。そうでない場合は、元の定義に戻ります。
this.b = 3;
console.log(this); //{a:1,b:2}
// return {a:999}; // このステップでは、{a:999}
が返されます。}
var obj = new Fun(); //obj = {a:1,b:2}、パラメータがない場合は、var obj = new Fun; と書くこともできます。 🎜>
5. 関数スコープ
JS 関数は入れ子にすることができます。複数の関数の入れ子は、JS のスコープ チェーンと呼ばれます。
JS スコープ チェーンの変数アクセス ルールは次のとおりです: アクセスする変数が現在のスコープに存在する場合は、現在のスコープの変数を使用します。そうでない場合は、グローバル スコープまで上位スコープ内を検索します。見つからない場合は、変数未申告です。
変数の宣言はコード解析期間中に完了することに注意してください。現在のスコープ内の変数の宣言と代入ステートメントが変数アクセスステートメントの後に記述されている場合、js 関数はその変数がすでにアクセスされているとみなします。は現在のスコープに存在し、上位レベルのドメイン検索には影響しません。ただし、変数の割り当てはコードの実行時に行われるため、アクセスされる変数は未定義になります。
例:
コードをコピー
関数 fun(){
アラート(a) //未定義
var a=10;
アラート(a) //10
アラート(b); //2
alert(c); //1000
}
楽しい();
}
アウト();
js では匿名関数の使用が非常に重要です。js 内のすべてのデータは関数を含めてオブジェクトであるため、関数はパラメーターや別の関数の戻り値として使用されることがよくあります。
匿名関数が保存されていない場合、実行後にメモリから解放されます。
匿名関数を呼び出す方法は、関数名の代わりに匿名関数を直接括弧内に置くことです。例:
(function(a,b){ return a b;})(1,2); //実行時に 2 つのパラメーターを渡して、匿名関数を宣言して実行します
//または
(function(a,b){ return a b;}(1,2));
//次の書き方は間違っています:
function(a,b){ return a b;}(1,2);
js のステートメントの終わりにあるセミコロンは省略できるため、js エンジンは function(a,b){ return a b;} がステートメントの終わりであると判断するため、匿名関数は宣言されているだけであり、ステートメントがパラメータ (1,2) を渡さない場合、() として記述された場合も、文法エラーが発生します。次の書き方が正しいです。
var ab = function(a,b){ return a b;}(1,2) // ab=3
js が文法を解析するときに、代入演算または演算子演算に式が出現する場合、それは「貪欲一致」 (可能な限り評価しようとする) です
function(t){ return 1 t;}(); //error
var f = function(t){ return t 1;}(); // ok
function(t){return t 1;}(); //ok
実際の開発では、
のように、匿名関数が操作値の形式で返される場合があります。
var a =1;var obj = {a:2,f:function(){ return this.a;}};
を指します。
匿名関数を宣言してすぐに実行することは、「自己実行関数」と呼ばれます。自己実行関数は、js コードをカプセル化するためによく使用されます。関数スコープの特性により、自己実行関数内の変数には外部からアクセスできません。関数内に配置されたコードは外部コードに影響を与えないため、変数汚染が回避されます。 JS 開発では変数汚染が発生しやすく、別のコーダーが開発中に同じ名前の変数や関数を定義すると、同じ名前の変数汚染が発生します。または関数を使用すると、後の関数が前の関数を上書きします。(関数(){
//独自のコード....
})(); 匿名関数は時間内にメモリを解放することもできます。変数は匿名関数内で宣言されているため、これらの変数が匿名関数の外部で参照されない場合、関数は実行を終了し、内部の変数が占有されます。メモリはすぐに解放されます。
関数の名前: Firefox などのブラウザでは、関数には関数の関数名である name 属性がありますが、この属性は IE には存在しません。また、匿名関数の名前は次のとおりです。空の。
var a=function(){}
alert(a.name); //未定義、a は匿名関数を格納する変数です。
function b(){}
alert(b . name); //b、ただし IE では未定義
7. 関数が呼び出されるとき、その関数は定義された環境で実行されます
関数がどこで、誰によって呼び出されたとしても、宣言時に構文環境を変更することはできません。これによって関数の実行環境が決まります。var inerFun=null;
関数 fun1(){
アラート(x);
}
関数ホルダー(){
var x = 100;
var fun2 = fun1;
inerFun = function(){alert(x);}
fun1() //99
fun2();//99
inerFun() //100
}
ホルダー();
fun1() //99
inerFun() //100
//別の例:
var x = 100;
var y=77;
var a1={
x:99,
xx:function(){
//var y=88; /この変数をコメントすると、y はグローバル変数になります 77
alter(y); //このポインタがないと、関数を呼び出すオブジェクトは関数の実行中に y の値に影響を与えることができません。ここからスコープ チェーンにステップインします。 Search value
alter(this.x) //このポインターを使用して、関数
}
}
a1.xx();
a1.xx.call(ウィンドウ);
var jj = a1.xx;
jj(); //効果は a1.xx.call(window); //次のコードを試してください。
var x=99;function xb(){
this.x=100;
this.a = (function(){return this.x}).call(this) / /new が実行され、匿名関数はインスタンス化されたオブジェクトによって呼び出されます
this.b = (function(){return this.x})(); //new が実行され、匿名関数は windowthis.method = function(){return this.x;}
}
console.log(xbObj.x);
console.log(xbObj.a);
console.log(xbObj.b);
console.log(xbObj.method());
関数を呼び出すオブジェクトの概念、関数を宣言するときの構文環境、および関数の構文環境の区別に注意してください。関数呼び出しステートメント
3. 関数呼び出しステートメントの構文環境によって、関数が実際に呼び出せるかどうか、またいつ呼び出せるかが決まります (関数が特定の構文環境で表示される場合にのみ、この関数を呼び出すことができます)
関数の実行中に、関数に渡されるパラメーターにアクセスするための引数オブジェクトが生成され、引数には関数自体を指すことができる属性があります: argument.callee.
関数の実行中、関数の caller 属性は、関数呼び出しステートメントが配置されている関数を指すことができます。たとえば、関数 a が関数 b の本体内で呼び出され、関数 a の実行中に a が呼び出されます。 .caller は関数 b を指します。 関数 a がグローバル環境で呼び出された場合、a.caller=null
引数と a.caller の値は、関数の各呼び出しに直接関係しており、関数の実行中に生成され、関数本体内でのみアクセスできます。
IE8 以前のブラウザでは、関数内の argument.caller (この属性は IE9 以降は削除されます) は、a.caller が実行されるときの引数 (arguments.caller.callee === a.caller) を指します。
7. リアルタイム文字列解析での関数呼び出し: eval()、new Function()、setTimeout()、setInterval()
eval() と window.eval()
var obj = Objinit ();
var param = 'outerParam';
console.log(param,obj.getParam()); //outerParam 123
obj.execute('param = 456');
console.log(param,obj.getParam()); //outerParam 456
obj.setCallback(function(){ eval("param = 8888")});
obj.fireCallback();
console.log(param,obj.getParam()) ; //8888 456
obj.setCallback(function(){ eval("eval(param = 9999)")});
obj.fireCallback();
console.log(param,obj.getParam) ()); //9999 456eval()
IE 中 ,window.execScript(); window.eval()
に相当しますnew Function()、setTimeout()、setInterval() の最初の文字列パラメータの解析で得られた代コードは、すべて実行されます。
八、函数闭包
関数のパケットを理解し、js のフレームワークの自動回復機能を事前に理解してください。数値、文字列、ブール値、未定義、null は、計算および赋值操作においては、オブジェクトの種類のデータベース按参照です、
js の同じオブジェクト型データは、特定のオブジェクトが再度参照されない場合、または 2 つのオブジェクト間の相互参照以外に第三方から参照されない場合、複数回参照される可能性があり、その占有を自動的に解放します。
関数の参照: 関数は他のオブジェクトのプロパティ値としてみなされるか、関数の内部で定義されたデータがこの関数の外で使用され、後続の状況に基づいてパケットが形成されます。 🎜>
复制代码}
楽しい(); //生産一闭包
f(); // 闭包中 a=2
f(); // 闭包中 a =3 ,模拟静态变量
在 fun 内的秘密関数数赋给 fun 外部的变量 f,该匿名関数内使用了 fun 内安全関数 a,これ以降、f は量 a を許可できますが、この制限を維持するために (f 実行時には許可 a が必要ですが、実行時間は未定です)、 fun() の実行で完全に生成された量 a は解放できません(f 中以外の関数は解放されます)その後、1 つの閉鎖パケットが生成されます (使用に備えて、閉鎖されています)。関数 A 内の推奨関数 B が A 以外に送信され、B 関数内で関数 A 内で生成されたデータ (推奨または按值渡し) が使用されている場合、
🎜>関数数B は関数数A を出力するほかの方法があります。例:
复制代码
代码如下:
原則として、関数の実行中にタイムパケットが形成され、関数の外部参照時にデータが存在せず、関数の実行が完了すると、タイム パケットの存続期間が短くなります。
闭パケットの独立性: 同じ関数によって生成された複数の闭パケットも互いに独立しています
代次如下:
var f2 = fun(); //另一份闭包
アラート(f1()); //2
alert(f1()); //3
alert(f2()); //2
alert(f2()); //3
2つのクロージャの変数aは異なるデータです。クロージャが生成されるたびにfun()が1回実行され、変数宣言文も1回実行されます。
JS oop プログラミングでは、クロージャーを使用してプライベート メンバーをシミュレートし、単一のクラスを構築できます
//プライベートメソッド
function setName(name){
myname=name;
}
//プライベート メソッド
function setVal(val){
myVal=val;
}
// new の実行時に内部プライベート メソッドを呼び出してオブジェクトを構築します
setName(name);
setVal(val);
//パブリック メソッド
this.getName=function(){
return myName
}
this.getVal=function(){
return myVal;
}
}
var obj = new MakeItem("name",100);
obj.myname; //未定義のプライベート プロパティには外部からアクセスできません
obj.getName() //ok
var instance = null; //在闭包中保存单体类的实例
var args = null;
var f = function(){
if(!instance){
if(this===window){
args = Array.prototype.slice.call(arguments,0);
instance = new arguments.callee();
}else{
this.init.apply(this,args||arguments);
instance = this;
}
}
return instance;
};
f.prototype = {
init:function(a,b,c){
this.a = a;
this.b = b;
this.c = c;
this.method1 = function(){ console.log("method 1"); };
this.method1 = function(){ console.log("method 1"); };
console.log("init instance");
}
};
f.prototype.constructor = f.prototype.init;
return f;
})();
//单体的使用
var obj1 = Singleton(1,2,3);
var obj2 = new Singleton();
var obj3 = new Singleton();
console.log(obj1===obj2,obj2===obj3); //true
console.log(obj1);
//一个单体类声明函数
var SingletonDefine= function(fun){
return (function(){
var instance = null;
var args = null;
var f = function(){
if(!instance){
if(this===window){
args = Array.prototype.slice.call(arguments,0);
instance = new arguments.callee();
}else{
fun.apply(this,args||arguments);
instance = this;
}
}
return instance;
};
f.prototype = fun.prototype;
f.prototype.constructor = fun;
return f;
})();
};
var fun = function(a,b,c){
this.a = a;
this.b = b;
this.c = c;
this.method1 = function(){ console.log("method 1"); };
console.log("init instance");
};
fun.prototype.method2 = function(){ console.log('method 2'); };
//Single class declaration function usage
var Singleton = SingletonDefine(fun);
var obj1 = Singleton(8,9,10);
var obj2 = new Singleton();
var obj3 = new Singleton(3,2,1);
console.log(obj1===obj2,obj2===obj3);
console.log(obj1);
//console.log(obj1.toSource()); //firefox
obj1.method1();
obj1.method2();
In IE 6, circular references to non-native js objects (DOM, etc.) will cause memory leaks. When using closures, be careful when using non-js native object references.
function fun(){
var node = document.getElementById('a');
node.onclick = function(){ alert(node.value); };
node = null; //Break circular references to prevent memory leaks
node saves DOM objects, which exist outside fun (and always exist, even if deleted, they are only removed from the document tree). After fun is executed, a closure is generated, which also constitutes a circular reference between the DOM object and the callback function ( node-function-node), a memory leak occurs under IE 6.