1、call和apply都是用来改变函数中的this关键字的
1)首先让当前函数执行
2)再把当前函数中的this改为传递的第一个参数值
var obj = {name: 'javascript'};
function print(){
console.log(this);
}
// 限制性print方法,再改变函数中的this为obj
print.call(obj); // object {name: 'javascript'}
2、call和apply的区别
function.call(this, arg1, arg2, .....) 当前执行函数若需要传递参数,则放在call方法中传递的this之后
function.apply(this, [arg1, arg2, ...]) 需要把当前函数的形参放在一个数组中传递进来
3、call和apply
1)JS非严格模式下,call和apply不传参数或者传null/undefined的时候默认this是window;严格模式下,不传参数的时候this是undefined,其余传谁就是谁。
第一个参数永远是用来改变this指向的。
var obj = {name: 'javascript'};
function print(arg1, arg2){
console.log(this);
}
print.call(1, 3); // this此时是1 输出结果 Number {1}
print.apply([1, 3]); // [1, 3]
function fn1() {
console.log(1);
}
function fn2() {
console.log(2);
}
fn1.call(fn2); // 1
fn1.call.call(fn2); // 2
// fn1.call执行
// 先让第二个call执行,这个call里面的this是fn1.call
// call方法执行的时候分为两步:
// 1、让里面的this变为fn2,即将原来的this(fn1.call)指向fn2
// 2、原来的this执行 现在就是fn2执行 输出2
// 此时前面的call只是起到了一个查找的作用
call, apply方法实现
// 实现一个call函数
Function.prototype.myCall = function (context) {
// 此时的this就是.call前面的那个方法
if(typeof this !== 'function'){
throw new TypeError(`${this} is not a function`);
}
// context不传值默认是window
context = context || window;
// 先用一个属性来保存原来的方法,即调用者本身
context.fn = this;
// 第一个参数是要改变的那个this指向,后面的参数都是要传入执行函数的参数
let arg = [...arguments].slice(1);
// 让原来的方法执行
let result = context.fn(...arg);
// 释放不用的空间
delete context.fn;
return result;
};
// 实现一个apply方法
Function.prototype.myApply = function(context){
if(typeof this !== 'function'){
throw new TypeError(`${this} is not a function`);
}
context = context || window;
context.fn = this;
let result;
if(arguments[1]){
result = context.fn(...arguments[1]);
}else{
result = context.fn();
}
delete context.fn;
return result;
}
call
,apply
方法都是改变this指向和执行函数一起完成,但是bind
方法只是改变了函数中的this指向,传递了参数,但并未执行函数,而是返回一个改变后的结果,体现了预处理思想,事先把this改变为我们想要的结果,并且传递了参数,以后要用时直接调用即可。
求数组最大最小值
var ary = [11, 25, 39, 10, 38, 9, 21, 17, 20, 30];
var maxNum, minNum;
方案一:先排序,首尾即最大最小值
ary.sort((a, b) => a - b);
maxNum = ary[ary.length - 1];
minNum = ary[0];
方案二:假设法
if(ary[0] < ary[1]){
minNum = ary[0];
maxNum = ary[1];
}else{
minNum = ary[1];
maxNum = ary[0];
}
for (let i = 2; i < ary.length; i++) {
ary[i] <= minNum ? minNum = ary[i] : void 0;
ary[i] >= maxNum ? maxNum = ary[i] : void 0;
}
方案三:借助apply传参的特点
// 不需要改this,随便传
maxNum = Math.max.apply(null, ary);
minNum = Math.min.apply(null, ary);
方案四:数组解构
maxNum = Math.max(...ary);
minNum = Math.min(...ary);
function fn1(){
alert(1);
}
function fn2(){
alert(2);
}
fn2.call(fn1); // 弹出2
fn2.call.call(fn1); // 弹出1
Function.prototype.call(fn1); // 不输出
Function.prototype.call.call(fn1); // 弹出1 等价于fn2.call.call(fn1);
多个call执行的,前面的都仅仅是从Function的原型上拿出call方法来执行,只有最后一个call才会让前面执行并让里面的this改变指向(变为fn1)
网友评论