Web前端之路让前端飞前端开发那些事

深入js中的call,apply方法

2017-10-24  本文已影响49人  luichooy

call(),apply()方法的作用都是用来改变函数运行时的上下文(Context),那么什么是上下文呢?

关于上下文

上下文就是函数中this的值,它的值等于函数运行时,调用这个函数的对象,也就是说,上下文是可以动态改变的,随着函数执行环境的不同,它的值也会发生变化。比如:

  1. 在全局作用于中调用函数,函数的上下文为Global对象(在浏览器中为window对象),eg:
var name = 'JavaScript';
function sayName (){
  console.log(this.name);
}
// 在全局作用域中调用sayName,此时相当与window.sayName();
// 所以此时的 this = window,即函数运行时的上下文为: window对象
sayName();     
  1. 在特定对象中调用函数,this指向这个对象,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','喵喵喵~~');
// 在对象mipang中调用函数speak,此时函数speak内部的指针指向mipang
// mipang有两个属性,name:'mipang',sound:'喵喵喵~~';
// 所以输出是: mipang speak 喵喵喵!!
mipang.speak();

call()、apply()语法

通过上面的例子,我们对上下文有了一个基本概念,此时我们再来讨论call(),apply()
如一开始所说,call()和apply()都是用来改变函数执行时的上下文的,两者的区别是传参方式的不同:

// call()具有多个参数,apply方法只有两个参数;
// 两者的第一个参数都是一个对象obj,用来改变函数function的上下文;
// 即 函数function中的this指向obj对象;

function.call(obj,arg1,arg2,arg3,...);   // 第一个参数后面的参数是一个参数列表
function.apply(obj,[arg1,arg2,arg3,...])  // 第二个参数是一个数组,数组的元素为函数的参数,即将call()方法的参数列表写成数组形式

我们举个例子来说一下call和apply的具体用法:

// 创建对象bajie,bajie有个introduce方法可以用来介绍自己的光辉事迹
var bajie = {
  name:  '猪八戒',
  introduce:  function (job,ability) {
    console.log(job + this.name + ability);
  }
}
bajie.introduce('天蓬大元帅','调戏嫦娥仙子'); //天蓬大元帅猪八戒调戏嫦娥仙子

// 创建对象wukong,wukong并没有一个介绍自己光辉事迹的introduce方法
var wukong = {
  name: '孙悟空'
}

假设我们想让wukong也有办法来介绍自己的光辉事迹,可以给对象wukong添加一个相同的introduce方法
假设我们也想给牛魔王、白骨精、金角大王等等相同的能力,难道要分别给每一个创建这个方法吗?当然不是,这个时候call(),apply()就派上用场了:

bajie.introduce.call(wukong,'齐天大圣','调戏嫂嫂铁扇公主');
bajie.introduce.apply(wukong,['齐天大圣','调戏嫂嫂铁扇公主']);
// 齐天大圣孙悟空调戏嫂嫂铁扇公主

我们来看一个实际应用场景:

function Animal(name,food,sound){
  this.name = name;
  this.food = food;
  this.sound = sound;
}
Animal.prototype.speak = function() {
  console.log(this.name+'爱吃'+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('咪胖','鱼','喵喵喵~');
cat.speak();   // 咪胖爱吃鱼    喵喵喵~

apply()方法特性:

apply方法会将默认将参数数组转换为参数列表,利用这一特性,有下面几个应用:

  1. 数组合并:
var arr1 = [1,2,3];
var arr2 = [4,5,6];
// 因为push()方法只接受参数列表,利用apply的特性将数组参数转为参数列表
arr1.push.apply(arr1,arr2);
// 或者Array.prototype.push.apply(arr1,arr2);
console.log(arr1);  // [1,2,3,4,5,6]
// 该方法接受参数列表,并将参数列表转为数组返回
function transtoArray(){
  var values = new Array();
  values.push.apply(values,arguments);
  return values;
}

var arr = transtoArray('张三','李四','王五','赵六');
console.log(arr);   // ['张三','李四','王五','赵六']
  1. 求的数组中的最大值和最小值
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
上一篇 下一篇

猜你喜欢

热点阅读