美文网首页
call,apply,bind方法

call,apply,bind方法

作者: 没了提心吊胆的稗子 | 来源:发表于2019-07-08 17:53 被阅读0次

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;
    }

callapply方法都是改变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)

相关文章

网友评论

      本文标题:call,apply,bind方法

      本文链接:https://www.haomeiwen.com/subject/htzohctx.html