javascriptの中のcall、appy、bindを簡単に話します.
6163 ワード
JavaScriptでは、call、appy、bindはFunctionオブジェクトが持つ3つの方法であり、この3つの方法の主な役割は関数のthisの指向を変えることで、花を接ぎ木`.本論文ではこの3つの方法を詳細に説明し、いくつかの古典的な応用シーンを列挙する.
call(thisArgs[,args...])
この方法は、運転中の関数の使用者、すなわち関数内のthisオブジェクトを指定したthisArgsパラメータとパラメータリストを渡すことができ、パラメータリストは呼び出し関数に入力されます.thisArgsの評価は以下の4つの場合があります.
(1)伝えない、またはnull、undefinedを伝え、関数の中のthisはwindowオブジェクトを指します.
(2)他の関数の関数名を伝え、関数のthisはこの関数の参照を指します.
(3)伝達文字列、数値またはブールタイプなどの基礎タイプで、関数の中のthisはString、Number、Booleanなどの対応する包装対象を指します.
(4)オブジェクトを伝達し、関数の中のthisはこのオブジェクトを指します.
apply(thisArgs[,args[])
applyとcallの唯一の違いは第二のパラメータの伝達方式が違っています.applyの第二のパラメータは配列でなければなりません.callはパラメータリストの伝達を許可します.注意すべきなのは、applyが受信したのはパラメータ配列ですが、関数を呼び出した時にはパラメータリストとして伝達されています.簡単な例を見ます.
ビッド(thisArgs[,args...])
bindはES 5によって新たに追加された方法であり、そのパスはコールと似ていますが、コール/applyとは著しい違いがあります.コールコールやapplyは自動的に対応する関数を実行します.bindは対応する関数を実行しません.関数への参照を返します.ざっと見ると、bindはcall/applyより遅れているようですが、ES 5はなぜbindを導入しますか?
実際には、ES 5がbindを導入する本当の目的は、call/applyの不足を補うために、call/applyがターゲット関数に対して自動的に実行されるため、イベントバインディング関数では使用できなくなります.bindは関数thisを変えることを実現すると同時に、目標関数を自動的に実行しないので、上記の問題を完璧に解決できます.例を見れば分かります.
JavaScriptにはJava、C((zhi)などの高級言語の中のextedキーワードがないので、JSには継承の概念がありません.もし継承したいなら、callとappyはこの機能を実現できます.
応用シーンその2:シフォンウッド
以下の内容を話す前に、まずJavaScriptの中の非標準専門用語を紹介します.ARrayLike(クラス配列/擬似配列)
ArayLikeオブジェクトは配列の一部を持っている行為で、DOMではすでに表現されていますが、jQueryの上昇によって、ArayLikeはJavaScriptで大いに異彩を放っています.ArayLikeオブジェクトの精妙はJS原生のArayと似ていますが、自由に構築されています.開発者からJavaScriptオブジェクトに対する拡張から来ています.つまり、プロトタイプはJS原生のArayを汚染することなく自由に定義できます.
ArayLikeオブジェクトは、JSで広く使用されています.例えば、DOMのNodeList、関数のアーグメンツは、配列のように各要素が格納されていますが、配列を操作する方法はありません.配列のいくつかの方法をcallでArayLikeオブジェクトに移動し、その要素を操作する目的を達成することができます.例えば、関数の中のargmentsをこのように遍歴することができます.
call(thisArgs[,args...])
この方法は、運転中の関数の使用者、すなわち関数内のthisオブジェクトを指定したthisArgsパラメータとパラメータリストを渡すことができ、パラメータリストは呼び出し関数に入力されます.thisArgsの評価は以下の4つの場合があります.
(1)伝えない、またはnull、undefinedを伝え、関数の中のthisはwindowオブジェクトを指します.
(2)他の関数の関数名を伝え、関数のthisはこの関数の参照を指します.
(3)伝達文字列、数値またはブールタイプなどの基礎タイプで、関数の中のthisはString、Number、Booleanなどの対応する包装対象を指します.
(4)オブジェクトを伝達し、関数の中のthisはこのオブジェクトを指します.
function a(){
console.log(this); // a this
}
function b(){} // b
var obj = {name:'onepixel'}; // obj
a.call(); //window
a.call(null); //window
a.call(undefined);//window
a.call(1); //Number
a.call(''); //String
a.call(true); //Boolean
a.call(b);// function b(){}
a.call(obj); //Object
これはコールの核心機能です.オブジェクトに定義されていない方法を呼び出すことができます.そしてこの方法はオブジェクトの属性にアクセスできます.このようにすると何かメリットがありますか?後でまた話します.簡単な例を見ます.
var a = {
name:'onepixel', // a
say:function(){ // a
console.log("Hi,I'm function a!");
}
};
function b(name){
console.log("Post params: "+ name);
console.log("I'm "+ this.name);
this.say();
}
b.call(a,'test');
>>
Post params: test
I'm onepixel
I'm function a!
b.callを実行すると、文字列`test`がパラメータとして関数bに伝達され、callの役割により、関数bのthisはオブジェクトaを指すので、オブジェクトaの関数bを呼び出すのに相当し、実際にはaにbは定義されていない.apply(thisArgs[,args[])
applyとcallの唯一の違いは第二のパラメータの伝達方式が違っています.applyの第二のパラメータは配列でなければなりません.callはパラメータリストの伝達を許可します.注意すべきなのは、applyが受信したのはパラメータ配列ですが、関数を呼び出した時にはパラメータリストとして伝達されています.簡単な例を見ます.
function b(x,y,z){
console.log(x,y,z);
}
b.apply(null,[1,2,3]); // 1 2 3
applyのこの特性はとても重要で、以下の応用シーンでこの特性を言及します.ビッド(thisArgs[,args...])
bindはES 5によって新たに追加された方法であり、そのパスはコールと似ていますが、コール/applyとは著しい違いがあります.コールコールやapplyは自動的に対応する関数を実行します.bindは対応する関数を実行しません.関数への参照を返します.ざっと見ると、bindはcall/applyより遅れているようですが、ES 5はなぜbindを導入しますか?
実際には、ES 5がbindを導入する本当の目的は、call/applyの不足を補うために、call/applyがターゲット関数に対して自動的に実行されるため、イベントバインディング関数では使用できなくなります.bindは関数thisを変えることを実現すると同時に、目標関数を自動的に実行しないので、上記の問題を完璧に解決できます.例を見れば分かります.
var obj = {name:'onepixel'};
/**
* document click , onClick
* bind onClick this obj, p1,p2
*/
document.addEventListener('click',onClick.bind(obj,'p1','p2'),false);
//
function onClick(a,b){
console.log(
this.name, //onepixel
a, //p1
b //p2
)
}
ウェブページをクリックする時、onClickは実行を触発されて、出力onepixel p 1 p 2、onClickの中のthisがbindによってobjオブジェクトに変更されたと説明しています.bindを深く理解するために、私達はbindのpolyfillの実現を見てみます.
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this, //this
fBound = function () {
return fToBind.apply(
// var obj = new fBound(), obj this, oThis
this instanceof fToBind
? this // this new obj
: oThis || this, // oThis , fBound this
// bind ,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
// ,
fBound.prototype = this.prototype;
// fBond ,
return fBound;
};
}
応用シーン一:継承JavaScriptにはJava、C((zhi)などの高級言語の中のextedキーワードがないので、JSには継承の概念がありません.もし継承したいなら、callとappyはこの機能を実現できます.
function Animal(name,weight){
this.name = name;
this.weight = weight;
}
function Cat(){
Animal.call(this,'cat','50');
//Animal.apply(this,['cat','50']);
this.say = function(){
console.log("I am " + this.name+",my weight is " + this.weight);
}
}
var cat = new Cat();
cat.say();//I am cat,my weight is 50
new演算子によってcatが生まれた場合、Catのthisはcatの対象を指していますが、継承の鍵はCatでAnimal.call(this,cat','50')を実行したことです.この言葉はcalでthisをサービングパラメータとして伝達しています.そこで、アニマル方法のthisはCatの中のthisを指しています.アニマルではnameとweightの属性が定義されており、catでこれらの属性が定義されていることに相当するため、catオブジェクトはアニマルで定義された属性を持っており、継承の目的を果たしている. 応用シーンその2:シフォンウッド
以下の内容を話す前に、まずJavaScriptの中の非標準専門用語を紹介します.ARrayLike(クラス配列/擬似配列)
ArayLikeオブジェクトは配列の一部を持っている行為で、DOMではすでに表現されていますが、jQueryの上昇によって、ArayLikeはJavaScriptで大いに異彩を放っています.ArayLikeオブジェクトの精妙はJS原生のArayと似ていますが、自由に構築されています.開発者からJavaScriptオブジェクトに対する拡張から来ています.つまり、プロトタイプはJS原生のArayを汚染することなく自由に定義できます.
ArayLikeオブジェクトは、JSで広く使用されています.例えば、DOMのNodeList、関数のアーグメンツは、配列のように各要素が格納されていますが、配列を操作する方法はありません.配列のいくつかの方法をcallでArayLikeオブジェクトに移動し、その要素を操作する目的を達成することができます.例えば、関数の中のargmentsをこのように遍歴することができます.
function test(){
// arguments Array
console.log(
arguments instanceof Array, //false
Array.isArray(arguments) //false
);
// arguments forEach
console.log(arguments.forEach); //undefined
// forEach arguments
Array.prototype.forEach.call(arguments,function(item){
console.log(item); // 1 2 3 4
});
}
test(1,2,3,4);
これ以外にも、applyにとっては、その独自の特性、すなわちapply受信は配列であり、呼び出し関数に伝達するときはパラメータリストで伝達される.この特性は、たとえばcallよりもapplyの方がはるかに優れているように見える.配列の中の最大要素を求めて、行列の中で最大値を得る方法がないことを知っています.一般的には、コードを書くことによって実現する必要があります.一方、Mathオブジェクトには最大値を取得する方法があり、Math.max()という方法があり、max方法はパラメータリストを転送して、これらのパラメータの最大値を返す必要があることを知っています.アプリは、Mathオブジェクトのmax方法を他のオブジェクトに適用するだけでなく、一つの配列をパラメータリストに変換してmaxに渡すこともでき、コードを見れば一目瞭然です.
var arr = [2,3,1,5,4];
Math.max.apply(null,arr); // 5
以上はcallとappyの古典的ないくつかの応用シーンです.これらの技術を熟練に把握して、これらの特性を実際のプロジェクトに応用すると、コードがより味わい深いように見えます.