JavaScript-関数Function

6510 ワード

機能
関数は実際にオブジェクトです.
各韓式はFunctionタイプの例であり、他の参照タイプと同様に属性と方法を有する.
関数オブジェクトのために、関数名は実際に関数オブジェクトを指すポインタでもあり、関数と結合されません.
関数の定義
function sum(num1, num2) {
    return num1 + num2;
}

var sum = function(num1, num2) {
    return num1 + num2;
}

var sum = new Function("num1", "num2", "return num1 + num2") //    
関数名は関数を指すポインタですので、関数名とオブジェクトポインタを含む他の変数は変わりません.
一つの関数には複数の名前(ポインタ)があります.例えば、
function sum(num1, num2) {
    return num1 + num2;
}
alert(sum(10, 10)); // 20

var anotherSum = sum;
alert(anotherSum(10, 10)); //20

sum = null;
alert(anotherSum(10, 10)); //20
上記の例では、関数を指す変数は、実際には関数オブジェクトを指すポインタであることが分かります.したがって、一つの割当値がnullである場合、他の変数には影響しません.
重負荷がない(深く理解する)
関数名を指針として想像すると、ECMAScriptに関数がない理由を理解するのに役立ちます.
function addSomeNumber(num) {
    return num + 100;
}

function addSomeNumber(num) {
    return num + 200;
}

var result = addSomeNumber(100); // 300
var addSomeNumber = function(num) {
    return num + 100;
}
addSomeNumber = function(num) {
    return num + 200;
}
二つの関数を宣言したが,結果は後の関数が前の関数を覆った.
関数宣言と関数式
解析器が実行環境にデータをロードする場合、関数に対する声明と関数の表現は同一視ではありません.
解析器は、まず関数宣言を読み取り、任意のコードを実行する前に利用できるようにします.
関数式は、解像度がそれらのコード行に実行されるまで、本当に実行される必要があります.
alert(sum(10, 10)); // 20
function sum(num1, num2){
    return num1 + num2;
}

alert(sum1(10, 10)) //   :TypeError: sum1 is not a function(…)
var sum1 = function(num1, num2){
    return num1 + num2;
}
宣言時に変数アクセス関数という点で区別できる以外に、関数宣言と関数表現の文法は実は等価です.
関数宣言と関数式を同時に使用することができますが、このような文法はSafariにおいてエラーを引き起こす可能性があります.
値の関数として
関数自体が変数ですので、関数も値として使用できます.
関数はパラメータのように関数を別の関数に渡すことができ、関数を別の関数の結果として返します.
function callSomeFunction(someFunction, someArgument) {
    return someFunction(someArgument);
}

function add10(num) {
    return num + 10;
}

var result1 = callSomeFunction(add10, 10);
alert(result1); // 20

function getGreetine(name) {
    return "Hello, " + name;
}

var result2 = callSomeFunction(getGreetine, "Bert");
alert(result2); // Hello, Bert
関数の内部属性
関数の内部には2つの特殊なオブジェクトがあります.
アーグメンントargumentsは、着信関数のすべてのパラメータを含む配列オブジェクトである.argumentsの主な用途は保存関数パラメータであるが、このオブジェクトにはcalleeという属性があり、この属性はポインタであり、このargumentsオブジェクトを持つ関数を指す.
function factorial(num) {
    if (num <= 1) {
        return 1;
    } else {
        return num * factorial(num -1);
    }
}

factorial(3) // 6

function factorial(num) {
    if (num <= 1) {
        return 1;
    } else {
        return num * arguments.callee(num -1);
    }
}

factorial(5) // 120
関数名を使う階乗は、関数名が変わったら再帰的に呼び出される関数の名前も変更されます.
しかし、arguments.calleeを使用すれば、関数名の変化にかかわらず、内部コードはエラーの心配がない.
this
関数内部の別の特殊オブジェクトは、JavaおよびC#thisと実質的に類似している.thisは、関数が実行する環境オブジェクト、またはthis値である(ウェブページのグローバルスコープで関数を呼び出した場合、thiswindowオブジェクト参照である).
window.color = "red";
var o = { color: "blue" };

function sayColor() {
    alert(this.color);
}

sayColor(); // red

o.sayColor = sayColor;
o.sayColor(); // blue
動作領域によっては、thisポインタが指すオブジェクトも異なる.
グローバルスコープでsayColor()を呼び出すと、thisはグローバルオブジェクトwindowを参照する.換言すればthis.colorの求値はwindow.colorに対する求値に変換され、
関数をオブジェクトoに割り当ててo.sayColor()を呼び出すと、thisはオブジェクトoを参照するので、this.colorに対して値を求めるとo.colorに変換され、結果としてbuleに戻る.
注意:関数の名前は、ポインタを含む変数だけです.したがって、異なる環境で実行されても、大域のsayColor()関数はo.sayColor()に指し示すものと同じ関数である.
caler
ECMAScript 5は他の関数オブジェクトの属性も規定しています.Operaの初期バージョンがサポートされていない以外、他のブラウザはこのECMAScript 3の属性をサポートしています.
この属性は、現在の関数を呼び出す関数の参照が保存されています.グローバルスコープで現在の関数を呼び出すと、彼の値はnullです.
function outer() {
    inter();
}

function inter() {
    alert(inter.caller);
    alert(arguments.callee.caller);
}

outer()
IE、Firefox、Chrome、Safariのすべてのバージョン、およびOpera 9.6は、caler属性をサポートします.
厳格なモードでargments.caleeにアクセスするとエラーが発生します.
厳密なモードでは関数caller属性に値を付けられません.
関数の属性と方法
length
関数が受信したい名前付きパラメータの個数
function sayName(name) {
    alert(name);
}

function sum(num1, num2) {
    return num1 + num2;
}

function sayHi() {
    alert("hi");
}

alert(sayName.length); // 1
alert(sum.length); // 2
alert(sayHi.length); // 0
プロトタイプ
ECMAScriptコアで定義されているグローバル属性の中で最も興味深いものはプロトタイプの属性です.
ECMAScriptにおける参照のタイプにとって、prototypeはそれらのすべての例示的な方法を保存する真の場所である.
tostring()やvalueOf()などの方法は、実際にプロトタイプの名前で保存されています.それぞれのオブジェクトのインスタンスを通じて訪問しただけです.
ユーザー定義の参照タイプを作成し、継承を実現するには、プロトタイプ属性の役割が極めて重要です.
prototype属性は列挙できないので、for-innを使うと見つけられません.
各関数には、引き継ぎではない2つの方法が含まれています.
これらの2つの方法の用途はいずれも特定の作用領域で関数を呼び出すものであり、実際には関数の内部のthisオブジェクトを設定する値に等しい.
appy()
二つのパラメータを受信します.一つは実行関数の作用領域で、もう一つはパラメータ配列です.ここで、第二のパラメータは、Arayの例であっても良いし、argmentsオブジェクトであっても良い.
function sum(num1, num2) {
    return num1 + num2
}

function callSum1(num1, num2) {
    return sum.apply(this, arguments);
}

function callSum2(num1, num2) {
    return sum.apply(this, [num1, num2]);
}

alert(callSum1(10, 10)); // 20
alert(callSum2(10, 10)); // 20
厳密なモードでは、環境オブジェクトを指定せずに関数を呼び出すと、this値はwindowに変換されません.特定のオブジェクトに関数を追加するか、またはappy()またはcall()を呼び出しないと、this値はundefinedとなります.
コール
call()方法はappy()方法と同じ役割をしていますが、それらの違いは受け入れパラメータの方式だけで違います.call()法に対して,最初のパラメータはthis値に変化がなく,変化はそのパラメータが直接関数に伝達されることである.
function sum(num1, num2) {
    return num1 + num2
}

function callSum(num1, num2) {
    return sum.call(this, num1, num2);
}

alert(callSum(10, 10)); // 20
伝達パラメータはappy()とcall()が本当に使う場所ではない.それらが本当に強いところは、関数依存を拡張して動作させることができるスコープです.
window.color = "red";
var o = {color: "blue"};

function sayColor() {
    alert(this.color);
}

sayColor.call(this); // red
sayColor.call(window); // red
sayColor.call(o); // blue
上記の例では、call()またはappy()を使用して、作用領域を拡張する最大の利点は、オブジェクトが方法との結合関係を必要としないことである.
ビッド()
この方法は、ビッド関数に伝える値に結合される関数の例を作成します.
window.color = "red";
var o = {color: "blue"};

function sayColor() {
    alert(this.color);
}

var objectSayColor = sayColor.bind(o);
objectSayColor(); // blue
Bind()メソッドをサポートするブラウザには、IE 9+、Firefox 4+、Safari 5.1+、Opera 12+、Chromeがあります.