call(),apply()
方法的作用都是用来改变函数运行时的上下文(Context),那么什么是上下文呢?
关于上下文
上下文就是函数中this
的值,它的值等于函数运行时,调用这个函数的对象,也就是说,上下文是可以动态改变的,随着函数执行环境的不同,它的值也会发生变化。比如:
- 在全局作用于中调用函数,函数的上下文为
Global
对象(在浏览器中为window
对象),eg:
var name = 'JavaScript';
function sayName (){
console.log(this.name);
}
// 在全局作用域中调用sayName,此时相当与window.sayName();
// 所以此时的 this = window,即函数运行时的上下文为: window对象
sayName();
- 在特定对象中调用函数,
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
方法会将默认将参数数组转换为参数列表,利用这一特性,有下面几个应用:
- 数组合并:
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); // ['张三','李四','王五','赵六']
- 求的数组中的最大值和最小值
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
网友评论