• JS高级——apply与call


    上下文调用模式

    可以修改this的值,也就是可以修改函数的调用方式,apply、call可以修改函数调用上下文,也就是this的值

    <script>
        var name = "莱昂纳多·自强·郭";
    
        function sayHello(a, b) {
            console.log(this.name + "吃了" + (a * b) + "个馒头");
        }
    
        var obj = {
            name: "尼古拉斯·电饭·锅"
        }
    
        var arr = [10, 20];
        sayHello.apply(obj, arr);//尼古拉斯·电饭·锅吃了200个馒头
        sayHello.call(obj, 2, 3);//尼古拉斯·电饭·锅吃了6个馒头
    </script>

    apply与call的区别

    函数.apply(对象, [函数需要参数列表,是一个数组])

    函数.call(对象,arg1,arg2,arg3...argn)

    具体区别就是apply参数是一个数组,而call传入函数的参数是一个值一个值的方式,所以根据他们的特性,运用情况也是不同:

    1、apply用于函数的形参个数不确定的情况

    2、call用于确定了函数的形参有多少个的时候使用

    apply与call应用于伪数组的场景

    (1)伪数组其实不是数组,并没有数组中的方法,但是表现形式却又很像数组

    <script>
        var obj = {
            0: 2,
            1: 3,
            2: 9,
            3: 20.
            length: 4
        }
    </script>

    上面其实是一个对象,但是如果拿obj.0来访问属性0对应的值是访问不了的,但是像数组一样访问obj['0']确实可以的,DOM里面的div元素的集合其实也是一个伪数组

    (2)利用apply与call可以轻易借用数组的方法操作伪数组

    <script>
        var obj = {
            0: 2,
            1: 3,
            2: 9,
            3: 20,
            length: 4
        }
        Array.prototype.push.call(obj, 100);
        console.log(obj);//{0: 2, 1: 3, 2: 9, 3: 20, 4: 100, length: 5}
        Array.prototype.splice.call(obj, 1, 1);
        console.log(obj);//{0: 2, 1: 9, 2: 20, 3: 100, length: 4}
    </script>

    (只有这样才会正常显示)

    当我们声明一个数组arr,arr有join()方法,执行的过程是遍历arr中的数据;arr对象的join方法其实是Array构造函数原型的方法,所有我们可以借用Array.prototype.join(),传递的第一个参数,是伪数组,上面提过join方法的执行过程的this就是遍历调用的对象arr,所以现在传递伪数组,改变了this,也会将伪数组遍历一遍

    案例分析

    (1)求一个数组的最大值

    <script>
        var arr = [9, 1, 4, 10, 7, 22, 8];
        //apply方法的第二个参数 是一个数组
        // 在调用的时候,会将数组中的每一个元素拿出来,作为形参,挨个传递给函数
        //apply方法和call方法第一个参数传递null的时候,都表示为函数调用模式
        //也就是将this指向window
        var max = Math.max.apply(null, arr);
        //==>等同于Math.max(9,1,4,10,7,22,8)
        console.log(max);//22
    </script>

    (2)将传入的参数打印,并且用’-‘连接

    <script>
        function foo() {
            //伪数组不具有join方法,所以这个时候就要考虑去借用一下数组的join方法
            //var str = Array.prototype.join.apply(arguments,["-"]);
            var str = [].join.apply(arguments, ["-"]);
            return str;
        }
    
        var str = foo(1, 3, "abc", "ffff", 99) // 1-3-abc-ffff-99
        console.log(str);
    </script>

    (3)设置div、p标签的颜色

    <script>
        var divs = document.getElementsByTagName('div');
        var ps = document.getElementsByTagName('p');
        var arr = [];
        arr.push.apply(arr, divs);
        arr.push.apply(arr, ps);
        for (var i = 0; i < arr.length; i++) {
            arr[i].style.backgroundColor = 'yellow';
        }
    </script>

     (4)打印简单类型真正的类型

    自定义类型的tostring方法最后输出的都是【object object】,但是简单类型输出的确实具体数值,那么,简单类型肯定重写了object的tostring方法,如果才能向自定义类型那样看到最后的类型

    <script>
        var a = [1, 2];
        console.log(a.toString());//1,2
        var obj = {
            name: 'qx'
        };
        console.log(obj.toString());//[object Object]
        console.log(Object.prototype.toString.call(a));//[object Array]
    </script>

    (5)

    <script>
        function test() {
            console.log(this);//Number {1}
            console.log(this.valueOf());
            console.log(+this);
            console.log("" + this);
        }
    
        test.apply(1);
        test.apply("abc");
        test.apply(true)
        test.apply(undefined)
    
        //当时用call和apply传入的第一个参数为值类型的时候
        //会将值类型转换成对应的对象(引用类型) 然后赋值给this
    
        //当传入的第一个参数为 null或者Undefined的时候,
        //会把this赋值为  window
    </script>

    (6)借用构造函数实现继承

    <script>
        //借用构造函数 实现继承
        function Person() {
            this.name = "张莎";
            this.age = 18;
        }
    
        function Student() {
            var stu = this;
            Person.apply(stu);
        }
    
        var stu = new Student();
        console.log(stu);
    </script>
  • 相关阅读:
    周总结(第十一周)
    周总结(第十周)
    周总结(第九周)
    周总结(第八周)
    周总结(第七周)
    周总结(第六周)
    周总结(第5周)
    周总结(第四周)
    周记
    补周记
  • 原文地址:https://www.cnblogs.com/wuqiuxue/p/8352256.html
Copyright © 2020-2023  润新知