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

例一

            var name = '小王',
                age = 17;
            var obj = {
                name: "小张",
                thisCopy: this, //this指向 window
                objAge: this.age, //this指向window
                myFun: function() {
                    console.log("obj-this", this) //this指向obj,obj没有age这个属性
                    // console.log(this.name + "年龄" + this.age)
                }
            }
            console.log(obj)
            console.log(this.age);//这个this指向window
            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;
                console.log('Person',this) //这里的this指向xiaoming这个实例
                this.sayname = function() {
                    console.log(this.name) //小明
                }
            }

            function Student(name) {
                console.log("arguments",arguments);//arguments 是函数参数组成的一个数组,类数组
                console.log('Student',this) //这里的this指向Student这个实例
                //apply将Person方法里的this指向由window指向xiaoming这个实例,并且直接执行
                Person.apply(this, arguments); //调用person并且把this指向Student,同时把Student的参数传过去,arguments是一个数组来的
            }

            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)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352