web-dev-qa-db-ja.com

JS .call()メソッドを使用する理由は?

JSにcall()メソッドがある理由は何ですか? thisを呼び出す通常の方法と重複しているようです。

たとえば、call()を使用したコードがあります。

var obj = {
    objType: "Dog"
}

f = function(did_what, what) {
    alert(this.objType + " " + did_what + " " + what);
}

f.call(obj, "ate", "food");

出力は「Dog ate food」です。しかし、同じ結果は、関数をオブジェクトに割り当てることができます。

var obj = {
    objType: "Dog"
}

f = function(did_what, what) {
    alert(this.objType + " " + did_what + " " + what);
}

obj.a = f;
obj.a("ate", "food");

結果は同じです。しかし、この方法はより理解しやすく使いやすいです。なぜcall()が必要ですか?

58
Green

callは、呼び出される関数で使用されるスコープを制御する場合に使用されます。 thisキーワードを、関数を割り当てたスコープ以外のものにしたい場合があります。これらの場合、callまたはapplyを使用して独自の関数を呼び出すことができます範囲。

F.exでは、「プライベート」関数を使用する場合など、スコープ外でユーティリティメソッドを呼び出すこともできます。

var obj = (function() {
    var privateFn = function() {
        alert(this.id);
    }
    return {
        id: 123,
        publicFn: function() {
            privateFn.call(this);
        }
    };
}());

obj.publicFn();

上記の例では、privateFnobjで公開されていませんが、パブリックスコープの一部であるかのように構築できます(thisを同じ方法で使用) 。

61
David Hellsing

2017アップデート

Function.prototypeによるすべての関数には_.call_メソッドがあります。 .call()を使用する理由は、変数 "this"が参照するものを指定するためです。

MDNの指定:

call()メソッドは、指定されたthis値と引数を個別に指定して関数を呼び出します。

以下を考慮してください。

_function x() {
    return this;
}

x()
_

厳格モードではx()は非厳格モードでundefinedを返し、ブラウザコンテキストではWindowを返します。

.call()を使用した例では、「this」が何を指すかを示しています。

_function x() {
    return this;
}

var obj = {
    myName      : 'Robert',
    myLocation  : 'Earth'
}

x.call(obj);
_

結果:_{myName: "Robert", myLocation: "Earth"}_。上記の例では、objオブジェクトを関数x()内のthisの値として指定しています。

OOPで継承をエミュレートするために使用できます。

例:

_var Robert = {
    name: "Robert Rocha",
    age: 12,
    height: "5,1",
    sex: "male",
    describe: function() {
        return "This is me " + this.name + " " + this.age + " " + this.height + " " + this.sex;
    }
};
_

上記がマスターオブジェクト(プロトタイプ)であり、別のオブジェクトで関数describeを継承するとします。

_var Richard = {
    name: "Richard Sash",
    age: 25,
    height: "6,4",
    sex: "male",
}
_

Richardオブジェクトには記述関数がなく、関数を単純に継承したいだけです。次のようにします:

_console.log( Robert.describe.call( Richard ) );
_

出力:_This is me Richard Sash 25 6,4 male_

39
Robert Rocha

例ではおそらく2番目の方法を使用しますが、あるオブジェクトの関数を別のオブジェクトで使用したい場合があります。例は、Arraysのような配列のようなオブジェクトでNodeListメソッドを使用することです

var el = document.getElementById("foo");
[].forEach.call(el.children, function(child, index) {
    //Iterate over an element's children, performing an action on each one
});
6
Dennis

ファーストクラス関数 の概念に関係しています。基本的に、Javascriptのような言語では、関数を独自のものとして扱うことができます。関数は変数に保存するか、他の関数に渡すことができます。

call()は、他のオブジェクトに関連付けられていない独立した関数を実行する方法を提供します。

3
Rob Agar