闲聊js中的apply、call和arguments

         JavaScript提供了apply和call两种调用方式来肯定函数中的this的指向,在现实编码中,我确实面试

不多接触到这两个方法。但很无奈,不少面试题都要考这两种方法,我又没怎么用到,因此咱们先来数组

闲聊下他们到底有什么用和到底怎么用。
         咱们先来聊一下apply的用法吧,它是用来改变函数的指向的,说白了,就是指向了别的函数的做用域。
浏览器

例如看一下下面这个例子。app

var A={
    name:"我是小A",
    fun:function(){
        console.log("你们好! "+this.name)
    }
}

var B = {
    name:"我是小B"
}

A.fun();           //你们好! 我是小A
A.fun.apply(B);    //你们好!  我是小B

能够看出来,当咱们使用了apply将引用指向了B时,A调用fun时并非调用自己中的name  而是调用了B中的那么;函数

但若是咱们在调用函数中并没用引用到this,那么是否是说apply就失去了意义?再来看一下下面的例子this

var A={
    name:"我是小A",
    fun:function(num,money){
        console.log("你们好! "+this.name+" 我有"+num+"张"+money+"块")
    }
}

var B = {
    name:"我是小B"
}
var monies = [10,20];

A.fun.apply(B,monies);    //你们好! 我是小B 我有10张20块

能够看出:apply中编码

  第一个参数为thisObject,调用时采用传入的thisObject代替函数体中this的指向spa

 第二个参数传入一个数组,函数会用数组的值取代“参数列表"。prototype

 

 

      这里聊一下monies,就要说到参数列表,固然咱们会想到arguments,在这里插入聊一下arguments。网code

上arguments是具备数组某些特性的‘类数组‘(伪数组);其实JS并无重载函数的功能,可是auguments对象

可以模拟重载。每一个函数都有一个Arguments对象实例arguments,它引用着函数的实参,能够用数组下

标的方式”[]“引用arguments的元素。arguments.length为函数实参个数。

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

匿名函数中能够用arguements.callee引用函数自身。

例如 function(){

         if(n>0) return 0;

          else return n+arguments.callee(n+1);

}

 

回归正题,咱们能够用arguments来代替函数中的参数

var A={
    name:"我是小A",
    fun:function(num,money){
        console.log("你们好! "+this.name+" 我有"+arguments[0]+"张"+arguments[1]+"块")
    }
}

var B = {
    name:"我是小B"
}
var monies = [10,20];

A.fun.apply(B,monies);    //你们好! 我是小B 我有10张20块

这里又有一个问题,可不能够用Array.prototype.shift.apply(arguments)来代替arguments[0]呢?直接看代码

var A={
    name:"我是小A",
    fun:function(num,money){
        console.log("你们好! "+this.name+" 我有"+Array.prototype.shift.apply(arguments)+"张"+arguments[1]+"块")
    }
}

var B = {
    name:"我是小B"
}
var monies = [10,20];

A.fun.apply(B,monies);    //你们好! 我是小B 我有10张undefined块

        当咱们使用Array.prototype.shift.apply(arguments)调用以后,arguments[0]就会被抹去,因此arguments[1]就会冒到arguments[0]上。

这能够看出arguments这个”伪数组“,除了不是”原型继承自’Array.prototype‘“职位,其余特征和数组是同样的。

 

        最后,咱们考虑一下,若是使用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就会指向全局的做用域。

 

apply的另外一种用法就是用于将数组分割为一个个元素。

例如想在数组中a[1,2,3,4]中寻找出最大的袁术出来。

若是直接调用Math.max(a);就会输出NaN,因此这时候咱们能够这样

Math.max.apply(null,a);        //输出4

 

      聊完了apply以后,咱们再聊一下call就更简单了,其实他们的做用都是同样的。他们惟一的区别就是

apply和call在形式参数上的不一样,apply只能传入两个参数且,第二个参数传入的是数组,而call在

第二参数开始能够接受任意个参数。你们看下面的例子就一目了然了

var A={
    name:"我是小A",
    fun:function(num,money){
        console.log("你们好! "+this.name+" 我有"+num+"张"+money+"块")
    }
}

var B = {
    name:"我是小B"
}
var monies = [10,20];
A.fun(monies[0],monies[1]);           //你们好! 我是小A 我有10张20块
A.fun.apply(B,monies);               //你们好! 我是小B 我有10张20块
A.fun.call(B,monies);                //你们好! 我是小B 我有10,20张undefined块
A.fun.call(B,monies[1],monies[2]);    //你们好! 我是小B 我有20张undefined块
相关文章
相关标签/搜索