为什么要用call()和apply()方法?apply、call、bind 这三个函数的存在意义是什么?答案是改变函数执行时的上下文,再具体一点就是改变函数运行时的this指向。现用以下例子说明
function cat(){}
cat.prototype = {
food:'fish',
say: function(){
console.log('I love '+this.food);
}
}
var blackCat = new cat();
blackCat.say();
call或者apply用法: 现在有一个对象whiteDog = {food:'bone'},我们不想对它重新定义say方法,那么我们可以通过call或apply用blackCat的say方法:blackCat.say.call(whiteDog);也可这种写法cat.prototype.say.call(whiteDog);
let whiteDog = {food:'bone'};
blackCat.say.call(whiteDog); //输出结果I love bone
//or
cat.prototype.say.call(whiteDog); //输出结果I love bone
bind用法: 现在有一个对象rabbit = {food:'carrot'},可这样写
let rabbit = {food:'carrot'};
let bind = cat.prototype.say.bind(rabbit); //返回一个函数
bind();//输出结果I love carrot
apply、call区别 仅在定义参数方式有所区别
xxx.say.call(test,"1","2");
xxx.say.apply(test,["1","2"]);
apply、call这两个方法在调用的时候,如果我们传入数字或者字符串,这两个方法会把传入的参数转成对象类型。
var number = 1;
function getThisType () {
var number = 3;
console.log('this指向内容',this); //this指向内容 Number {1}
console.log(Object.prototype.toString.call(this)) //[object Number]
}
getThisType.call(number);
call和apply改变了函数的this上下文后便执行该函数,而bind则是返回改变了上下文后的一个函数。
关于call、apply的题集
- 1 怎么利用call、apply来求一个数组中最大或者最小值,Demo如下所示:
let arr = [1, 2, 19, 6];
console.log(Math.max.call(null, 1,2,19,6)); // 输出结果:19
console.log(Math.max.apply(null, arr)); // 输出结果:19
- 2 将伪数组转化为数组,伪数组是指具有length属性,且可以通过0、1、2…下标来访问其中的元素,但是没有Array中的push、pop等方法,就可以利用call,apply来转化成真正的数组,Demo如下所示:
let obj = {
0: 'candy',
1: 'thomas',
2: 'peter',
length: 3 // 一定要有length属性
};
console.log(Array.prototype.slice.call(obj));
//输出结果:['candy','thomas','peter']
- 3 利用call和apply做继承,Demo如下所示:
function Animal(name){
this.name = name;
this.showName = function(){
console.log(this.name);
}
}
function Cat(name){
Animal.call(this, name);
}
// Cat对象就能够直接调用Animal的方法以及属性了
var cat = new Cat("Candy");
cat.showName();
//输出结果:Candy
caller functionName.caller 返回一个对函数的引用,该函数调用了当前函数。对于函数来说,caller 属性只有在执行时才有定义。如果函数是由 Javascript 程序的顶层调用的,那么 caller 包含的就是 null 。
function callerDemo() {
if (callerDemo.caller) {
var a= callerDemo.caller.toString();
console.log(a);
} else {
console.log("this is a top function");
}
}
function handleCaller() {
callerDemo();
}
handleCaller();
//输出结果:"function handleCaller() { callerDemo();}"
callee 返回正被执行的 Function 对象,也就是所指定的 Function 对象的正文。 callee 属性是 arguments 对象的一个成员,它表示对函数对象本身的引用,这有利于匿名函数的递归或者保证函数的封装性. ES5 提示: 在严格模式下,arguments.callee 会报错 TypeError,因为它已经被废除了。 arguments.length是实参长度,arguments.callee.length是形参长度
//callee可以打印其本身
function calleeDemo() {
console.log(arguments.callee);
}
calleeDemo();
//输出结果:function calleeDemo() { console.log(arguments.callee);}
//callee用于验证参数
function calleeLengthDemo(arg1, arg2) {
if (arguments.length == arguments.callee.length) {
window.alert("验证形参和实参长度正确!");
return;
} else {
alert("实参长度:" + arguments.length);
alert("形参长度: " + arguments.callee.length);
}
}
//callee递归计算
var sum = function (n) {
if (n < = 0)
return 1;
else
return n +arguments.callee(n - 1)
}