美文网首页
2020-07-09avaScript 中 call()、app

2020-07-09avaScript 中 call()、app

作者: zsyyyyy | 来源:发表于2020-07-09 11:29 被阅读0次

    例一

                var name = '小王',
                    age = 17;
                var obj = {
                    name: "小张",
                    objAge: this.age,//this指向obj
                    myFun: function() {
                        //console.log("obj-this", this) //this指向obj
                        console.log(this.name + "年龄" + this.age)
                    }
                }
                console.log(obj.objAge) //17
                obj.myFun(); //小张年龄 undefined
    

    例2

                var fav = "盲僧"
                function shows() {
                    //              console.log("shows-this", this) //this指向window
                    console.log(this.fav)
                }
                shows() //盲僧
    

    比较一下这两者 this 的差别,第一个打印里面的 this 指向 obj,第二个全局声明的 shows() 函数 this 是指向window ;

    1,call()、apply()、bind() 都是用来重定义 this 这个对象的!
                var name = '小王',
                    age = 17;
                    var obj = {
                        name: "小张",
                        objAge: this.age,
                        myFun: function() {
                            console.log("obj-this", this) //this指向obj
                            console.log(this.name + "年龄" + this.age)
                              }
                          }
                var db = {
                    name: "德玛",
                    age: "89"
                }
                obj.myFun();//小张年龄underfind  myFun的this指向obj
                var myFunA= obj.myFun;
                //myFunA在外部调用,此时的this指向了全局对象
                myFunA();//小王年龄17
                 //为了保证this指向不变,我们可以通过bind方法绑定this指向
                //如:
                var myFunA2= obj.myFun.bind(obj);
                console.log(myFunA2()); //小张年龄underfind 需要调用才执行
                //此时可以看到this的指向保持指向了obj这个对象。
    
                var myFunA3 = obj.myFun.call(obj);
                console.log(myFunA3 ); //小张年龄underfind 不需要调用就执行
                var myFunA4 = obj.myFun.apply(obj);
                console.log(myFunA4); //小张年龄underfind 不需要调用就执行
                //此时你会发现当我们用call或者apply方法来保证this指向的时候,
               //call和apply方法会直接执行掉myFun这个方法,不需要调用。
    
    
                //obj.myFun方法里的this由obj指向db
                obj.myFun.call(db) // 德玛年龄 89
                obj.myFun.apply(db) // 德玛年龄 89
    
                console.log(obj.myFun.bind(db)) //bind 返回的是一个新的函数,你必须调用它才会被执行。
                obj.myFun.bind(db)() //调用bind返回的函数 // 德玛年龄 89
    
    

    以上出了 bind 方法后面多了个 () 外 ,结果返回都一致!
    由此得出结论,bind和call,apply的区别,bind 返回的是一个新的函数,.只会改变函数this指向不会执行函数,你必须调用它才会被执行,call和apply会改变this指向并且直接执行了函数

    2,对比call 、bind 、 apply 传参情况下
                var name = '小王',
                    age = 17;
                var obj = {
                    name: "小张",
                    objAge: this.age,
                    myFun: function(fm, ft) {
                        console.log("obj-this", this) //this指向obj
                        console.log(this.name + "年龄" + this.age, " 来自 " + fm + " 去往  " + ft)
                    }
                }
                var db = {
                    name: "德玛",
                    age: "89"
                }
    
                obj.myFun.call(db, "广州", "深圳") //德玛年龄89  来自 广州 去往  深圳
                obj.myFun.apply(db, ["广州", "深圳"]) // 德玛年龄89  来自 广州 去往  深圳
    
                obj.myFun.bind(db, "广州", "深圳")() //德玛年龄89  来自 广州 去往  深圳
                obj.myFun.bind(db, ["广州", "深圳"])() //德玛年龄89  来自 广州,深圳 去往  undefined
                //例2
                var obj = {
                    a:2,
                    sum:function(b,c){
                        return this.a + b + c;
                    }
                }
    
                var sum0 = obj.sum;
    
               //分别用bind,call,apply方法来调用sum0方法。
               var sum1 = sum0.bind(obj,2,3);
               console.log(sum1()); // 7
    
               var sum2 = sum0.call(obj,2,3);
               console.log(sum2); // 7
    
               var sum3 = sum0.apply(obj,[2,3]);
               console.log(sum3); // 7
    
        从这里我们可以看出bind和call方法传入参数方式和apply方式不一样。
    
    

    // 微妙的差距!
    //
    // 从上面四个结果不难看出:
    //
    // call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,第二个参数差别就来了:
    //
    // call 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔,直接放到后面 obj.myFun.call(db,'成都', ... ,'string' )。
    //
    // apply 的所有参数都必须放在一个数组里面传进去 obj.myFun.apply(db,['成都', ..., 'string' ])。
    //
    // bind 除了返回是函数以外,它 的参数和 call 一样。
    //
    // 当然,三者的参数不限定是 string 类型,允许是各种类型,包括函数 、 object 等等!
    总结:
    call和bind方法可以传入多个参数,第二个参数后的所有参数都传入调用的函数中,apply方法只能传入两个参数,且第二参数为数组,数组里面的元素传入到调用的函数中。

    最后,我们考虑一下,如果使用apply方法时,传入的第一个参数是null时,调用函数时,会发生什么情况,会不会报错呢!
    不多说,直接上例子

    var A={
        name:"我是小A",
        fun:function(num,money){
            console.log("大家好! "+this.name+" 我有"+num+"张"+money+"块")
        }
    }
    
    var B = {
        name:"我是小B"
    }
    var monies = [10,20];
    name="我是小C"
    
    A.fun.apply(null,monies);    //大家好! 我是小C 我有10张20块
    

    可以看到 如果第一传入的参数是null的话,在函数提内的this会指向全局对象,在浏览器中就是window。

    所以可以总结出两点:

    1.如果函数中有明确使用this,那么this就会指向传入的第一个参数的作用域。

    2.如果传入的第一参数为null时,this就会指向全局的作用域。

    fn.apply(this, arguments)将函数的属性与方法进行拷贝,bai主要是实现类的继承。
            function Person(name){
                    this.name=name;
                    this.sayname=function (){
                         console.log(this.name)//小明
                    }
                }
            function Student(name){
                    console.log(this)//这里的this指向xiaoming这个实例
                    //apply将Person方法里的this指向由window指向xiaoming这个实例,并且直接执行
                    Person.apply(this,arguments);//arguments作为Person()函数的实参,是一个数组来的
                }
                 
            var xiaoming  =  new Student("小明");
            xiaoming.sayname();
            //这样Student类拷贝了Person的属性和方法,实现了类的继承
            //忘记加上new命令,结果是this指向了全局作用域
    

    部分转自:https://www.runoob.com/w3cnote/js-call-apply-bind.html

    js中arguments详解

    微信图片_20200724110937.png

    一、简介

    了解arguments这个对象之前先来认识一下javascript的一些功能:
    其实Javascript并没有重载函数的功能,但是Arguments对象能够模拟重载。Javascrip中每个函数都会有一个Arguments对象实例arguments,它引用着函数的实参,可以用数组下标的方式"[]"引用arguments的元素。arguments.length为函数实参个数,arguments.callee引用函数自身。


    微信图片_20200724111553.png 微信图片_20200724111558.png

    三、使用方法
    虽然arguments对象并不是一个数组(类数组),但是访问单个参数的方式与访问数组元素的方式相同

    例如:
    arguments[0],arguments[1],。。。arguments[n]; 在js中 不需要明确指出参数名,就能访问它们

    例如:

    function test() {
            var s = "";
            for (var i = 0; i < arguments.length; i++) {
                alert(arguments[i]);
                s += arguments[i] + ",";
            }
            return s;
    }
    test("name", "age");
    
    输出结果:
    name,age
    

    我们知道每一个对象都有自己的属性,arguments对象也不例外,首先arguments的访问犹如Array对象一样,用0到arguments.length-1来枚举每一个元素。下面我们来看看callee属性,返回正被执行的** Function** 对象,guments.callee就是函数自身。,实现匿名的递归函数。代码如下:

    var sum = function (n) {
            if (1 == n) {
                return 1;
            } else {
                return n + arguments.callee(n - 1); //6 5 4 3 2 1
            }
       }
       alert(sum(6));
    
    输出结果:21
    

    传多个参数事可以直接用argument,比如求最大值:

    function max() {
            var max = arguments[0];
            console.log(arguments)
    
            for (val of arguments) {
                if (val >= max) {
                    max = val;
                }
            }
            return max;
        }
        var maxValue = max('9', 1, 2, 4)
        console.log(maxValue)
    
         //apply的另一种用法就是用于将数组分割为一个个元素。
         //例如想在数组中a[1,2,3,4]中寻找出最大的袁术出来。
        //利用apply求最大值:
        var a = [1, 2, 3, 4];
        console.log(Math.max(a))
        console.log(Math.max.apply(null, a)); //输出4)
    
    

    相关文章

      网友评论

          本文标题:2020-07-09avaScript 中 call()、app

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