javascript call和apply的用法
阿新 • • 發佈:2018-12-18
存在call和apply的意義
function cat(){
}
cat.prototype={
food:"fish",
say: function(){
console.log("I love "+this.food);
}
}
var blackCat = new cat;
blackCat.say() //I love fishI love fish
我們定義了一個建構函式cat,又在cat的原型裡邊定義了一個方法say,例項化了一個物件blackcat,呼叫原型裡邊的say方法
但是如果我們有一個物件whiteDog = {food:"bone"},我們不想對它重新定義say方法,那麼我們可以通過call或apply用blackCat的say方法:blackCat.say.call(whiteDog);
function cat(){
}
cat.prototype={
food:"fish",
say: function(){
console.log("I love "+this.food);
}
}
var blackCat = new cat;
blackCat.say() //I love fishI love fish
var whiteDog = {food:"bone"},
blackCat.say.call(whiteDog) //I love bone
所以,可以看出call和apply是為了動態改變this而出現的,當一個object沒有某個方法,但是其他的有,我們可以藉助call或apply用其它物件的方法來操作
定義
call 和 apply 都是為了改變某個函式執行時的 context 即上下文而存在的,換句話說,就是為了改變函式體內部 this 的指向apply([thisObj [,argArray] ])
呼叫一個物件的一個方法,另一個物件替換當前物件
apply()方法 接收兩個引數,一個是函式執行的作用域(this),另一個是引數陣列
//例1 <script> window.number = 'one'; document.number = 'two'; var s1 = {number: 'three' }; function changeColor(){ console.log(this.number); } changeColor.apply(); //one (預設傳參) changeColor.apply(window); //one changeColor.apply(document); //two changeColor.apply(this); //one changeColor.apply(s1); //three </script> //例2 function Pet(words){ this.words = words; this.speak = function () { console.log( this.words) } } function Dog(words){ //Pet.call(this, words); //結果: Wang Pet.apply(this, arguments); //結果: Wang } var dog = new Dog('Wang'); dog.speak();
call([thisObject[,arg1 [,arg2 [,…,argn]]]])
應用某一物件的一個方法,用另一個物件替換當前物件
call()方法 第一個引數和apply()方法的一樣,但是傳遞給函式的引數必須列舉出來
<script>
window.color = 'red';
document.color = 'yellow';
var s1 = {color: 'blue' };
function changeColor(){
console.log(this.color);
}
changeColor.call(); //red (預設傳遞引數)
changeColor.call(window); //red
changeColor.call(document); //yellow
changeColor.call(this); //red
changeColor.call(s1); //blue
</script>
//例2
var Pet = {
words : '...',
speak : function (say) {
console.log(say + ''+ this.words)
}
}
Pet.speak('Speak'); // 結果:Speak...
var Dog = {
words:'Wang'
}
//將this的指向改變成了Dog
Pet.speak.call(Dog, 'Speak'); //結果: SpeakWang
區別
call物件後面的引數是引數列表,而apply物件後面的引數是陣列
function add(c,d){
return this.a + this.b + c + d;
}
var s = {a:1, b:2};
console.log(add.call(s,3,4)); // 1+2+3+4 = 10
console.log(add.apply(s,[5,6])); // 1+2+5+6 = 14
類陣列
這裡把符合以下條件的物件稱為類陣列
1.具有length屬性
2.按索引方式儲存資料
3.不具有陣列的push,pop等方法
常見類陣列有 arguments,NodeList
(function(){
Array.prototype.push.call(arguments,4);
console.log(arguments);//[1, 2, 3, 4]
})(1,2,3)
這樣就往arguments中push一個4進去了
Array.prototype.push 頁可以實現兩個數組合並
同樣push方法沒有提供push一個數組,但是它提供了push(param1,param,…paramN) 所以同樣也可以通過apply來裝換一下這個陣列,即
var arr1=new Array("1","2","3");
var arr2=new Array("4","5","6");
Array.prototype.push.apply(arr1,arr2);
console.log(arr1);//["1", "2", "3", "4", "5", "6"]
也可以這樣理解,arr1呼叫了push方法,引數是通過apply將陣列裝換為引數列表的集合
再比如我想求類陣列中的最大值
(function(){
var maxNum = Math.max.apply(null,arguments);
console.log(maxNum);//56
})(34,2,56);
判斷型別
console.log(Object.prototype.toString.call(123)) //[object Number]
console.log(Object.prototype.toString.call('123')) //[object String]
console.log(Object.prototype.toString.call(undefined)) //[object Undefined]
console.log(Object.prototype.toString.call(true)) //[object Boolean]
console.log(Object.prototype.toString.call({})) //[object Object]
console.log(Object.prototype.toString.call([])) //[object Array]
console.log(Object.prototype.toString.call(function(){})) //[object Function]