2020-07-09avaScript 中 call()、apply()、bind() 的用法

例一

            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()、apply()、bind() 的用法)