深入js中的call,apply方法

call(),apply()方法的作用都是用來(lái)改變函數(shù)運(yùn)行時(shí)的上下文(Context),那么什么是上下文呢?

關(guān)于上下文

上下文就是函數(shù)中this的值,它的值等于函數(shù)運(yùn)行時(shí),調(diào)用這個(gè)函數(shù)的對(duì)象,也就是說(shuō),上下文是可以動(dòng)態(tài)改變的,隨著函數(shù)執(zhí)行環(huán)境的不同,它的值也會(huì)發(fā)生變化。比如:

  1. 在全局作用于中調(diào)用函數(shù),函數(shù)的上下文為Global對(duì)象(在瀏覽器中為window對(duì)象),eg:
var name = 'JavaScript';
function sayName (){
  console.log(this.name);
}
// 在全局作用域中調(diào)用sayName,此時(shí)相當(dāng)與window.sayName();
// 所以此時(shí)的 this = window,即函數(shù)運(yùn)行時(shí)的上下文為: window對(duì)象
sayName();     
  1. 在特定對(duì)象中調(diào)用函數(shù),this指向這個(gè)對(duì)象,eg:
function Cat(name,sound) {
  this.name = name;
  this.sound = sound;
}
Cat.prototype.speak =function () {
  console.log(`${this.name} speak ${this.sound}`);
}
var mipang = new Cat('mipang','喵喵喵~~');
// 在對(duì)象mipang中調(diào)用函數(shù)speak,此時(shí)函數(shù)speak內(nèi)部的指針指向mipang
// mipang有兩個(gè)屬性,name:'mipang',sound:'喵喵喵~~';
// 所以輸出是: mipang speak 喵喵喵??!
mipang.speak();

call()、apply()語(yǔ)法

通過(guò)上面的例子,我們對(duì)上下文有了一個(gè)基本概念,此時(shí)我們?cè)賮?lái)討論call(),apply()
如一開(kāi)始所說(shuō),call()和apply()都是用來(lái)改變函數(shù)執(zhí)行時(shí)的上下文的,兩者的區(qū)別是傳參方式的不同:

// call()具有多個(gè)參數(shù),apply方法只有兩個(gè)參數(shù);
// 兩者的第一個(gè)參數(shù)都是一個(gè)對(duì)象obj,用來(lái)改變函數(shù)function的上下文;
// 即 函數(shù)function中的this指向obj對(duì)象;

function.call(obj,arg1,arg2,arg3,...);   // 第一個(gè)參數(shù)后面的參數(shù)是一個(gè)參數(shù)列表
function.apply(obj,[arg1,arg2,arg3,...])  // 第二個(gè)參數(shù)是一個(gè)數(shù)組,數(shù)組的元素為函數(shù)的參數(shù),即將call()方法的參數(shù)列表寫(xiě)成數(shù)組形式

我們舉個(gè)例子來(lái)說(shuō)一下call和apply的具體用法:

// 創(chuàng)建對(duì)象bajie,bajie有個(gè)introduce方法可以用來(lái)介紹自己的光輝事跡
var bajie = {
  name:  '豬八戒',
  introduce:  function (job,ability) {
    console.log(job + this.name + ability);
  }
}
bajie.introduce('天蓬大元帥','調(diào)戲嫦娥仙子'); //天蓬大元帥豬八戒調(diào)戲嫦娥仙子

// 創(chuàng)建對(duì)象wukong,wukong并沒(méi)有一個(gè)介紹自己光輝事跡的introduce方法
var wukong = {
  name: '孫悟空'
}

假設(shè)我們想讓wukong也有辦法來(lái)介紹自己的光輝事跡,可以給對(duì)象wukong添加一個(gè)相同的introduce方法
假設(shè)我們也想給牛魔王、白骨精、金角大王等等相同的能力,難道要分別給每一個(gè)創(chuàng)建這個(gè)方法嗎?當(dāng)然不是,這個(gè)時(shí)候call(),apply()就派上用場(chǎng)了:

bajie.introduce.call(wukong,'齊天大圣','調(diào)戲嫂嫂鐵扇公主');
bajie.introduce.apply(wukong,['齊天大圣','調(diào)戲嫂嫂鐵扇公主']);
// 齊天大圣孫悟空調(diào)戲嫂嫂鐵扇公主

我們來(lái)看一個(gè)實(shí)際應(yīng)用場(chǎng)景:

function Animal(name,food,sound){
  this.name = name;
  this.food = food;
  this.sound = sound;
}
Animal.prototype.speak = function() {
  console.log(this.name+'愛(ài)吃'+this.food+'    '+this.sound);
}
function Cat(name,food,sound) {
  // Animal.call(this,name,food,sound);
  Animal.apply(this,arguments);
}
Cat.prototype = new Animal();
var cat = new Cat('咪胖','魚(yú)','喵喵喵~');
cat.speak();   // 咪胖愛(ài)吃魚(yú)    喵喵喵~

apply()方法特性:

apply方法會(huì)將默認(rèn)將參數(shù)數(shù)組轉(zhuǎn)換為參數(shù)列表,利用這一特性,有下面幾個(gè)應(yīng)用:

  1. 數(shù)組合并:
var arr1 = [1,2,3];
var arr2 = [4,5,6];
// 因?yàn)閜ush()方法只接受參數(shù)列表,利用apply的特性將數(shù)組參數(shù)轉(zhuǎn)為參數(shù)列表
arr1.push.apply(arr1,arr2);
// 或者Array.prototype.push.apply(arr1,arr2);
console.log(arr1);  // [1,2,3,4,5,6]
// 該方法接受參數(shù)列表,并將參數(shù)列表轉(zhuǎn)為數(shù)組返回
function transtoArray(){
  var values = new Array();
  values.push.apply(values,arguments);
  return values;
}

var arr = transtoArray('張三','李四','王五','趙六');
console.log(arr);   // ['張三','李四','王五','趙六']
  1. 求的數(shù)組中的最大值和最小值
var arr = [1,8,5,4,5,9,6,3,7];
var maxValue = Math.max.apply(null,arr);
console.log(maxValue);   // 9
var minValue = Math.min.apply(null,arr);
console.log(minValue);   // 1
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容