Javascript函数调用的四种方式

一、Javascript函数的特点

Javascript中函数有两个主要特点使其显得比较特殊。第一个特点在于函数是第一类对象,第二个特点在于它们可以提供作用域。函数就是对象,其表现如下:

  • 函数可以在运行时动态创建,还可以在程序执行过程中创建
  • 函数可以分配给变量,可以将它们的引用复制到其他变量,可以被扩展,此外除了少数特殊情况外,函数还可以被删除
  • 可以作为参数传递给其他函数,并且还可以由其他函数返回
  • 函数可以有自己的属性和方法

二、Javascript中函数定义方式

方式一:
var add = function(a,b){ //函数表达式
    return a + b;
};
方式二:
function add(a,b){ //函数声明
    return a + b;
}
方式三:
var add = new Function('a,b','return a + b');//不推荐使用  

Javascript是一种解释性的语言,函数声明会在Javascript代码加载后、执行前被解释,而函数表达式只有在执行到这一行代码时才会被解释。函数声明中不需要分号结尾,但在函数表达式中需要分号,并且应该总是使用分号。

函数表达式VS函数声明:名称和变量声明提升

alert(add(10,10));//正常调用
function add(a,b){
    return a + b;
}
以上代码可以正常运行。因为在代码开始执行之前,解析器就已经读取函数声明并将其添加到执行环境中。  
若下面例子所示,把上面的函数声明改为使用函数表达式方式,就会在执行期间导致错误:  
alert(add(10,10));  
var add = function(a,b){
    return a + b ;
};  

三、Javascript中四种调用方式

1、方法调用模式
当一个函数被保存为对象的一个属性时,我们称它为一个方法。当一个方法被调用时,this被绑定到该对象。如果调用表达式包含一个提取属性的动作(即包含一个.或[subscript]下标表达式),那么它就当做一个方法来调用。

var myObject = {
    value : 0,
    increment:function(inc){
        this.value += typeof inc === 'number' ? inc : 1;
        console.log(inc);
    }
 }  

方法可以使用this访问自己所属的对象,所以它能从对象中取值或对对象进行修改。this到对象的绑定发生在调用的时候。这个延时绑定使得函数可以对this高度复用。
2、函数调用模式
当一个函数并非一个对象的属性时,那么它就是被当做一个函数来调用:
var sum = add(3,4);
以此模式调用函数时,this被绑定到全局对象。这是语言设计上的一个错误,倘若语言设计正确,那么当内部函数被调用时,this应该仍然绑定到外部函数的this变量。这个设计错误的后果就是方法不能利用内部函数来帮助它工作,因为内部函数的this被绑定了错误的值,所以不能共享方法对对象的访问权。如果该方法定义一个变量并给它赋值为this,那么内部函数就可以通过那个变量访问到this。按照约定我们把那个变量命名为that:

myObject.double = function (){//给myObject增加一个double方法  
    var that = this;
    var helper = function (){
        that.value = add(that.value,that.value);
        console.log(this);
    };
    helper();//以函数的形式调用helper
};
myObject.double();//以方法的形式调用double  

3、构造器调用模式
当以new操作符调用构造函数时,函数内部将会发生以下情况:

  • 创建一个空对象并且this变量引用了该对象,同时还继承了该函数的原型
  • 属性和方法被加入到this引用的对象中
  • 新创建的对象由this所引用,并且最后隐式地返回this(如果没有显式地返回其他对象)
    以上情况看起来就像是在后台发生了如下事情:

    var Person = function(name){
        //使用对象字面量创建一个新对象
        //var this = {};          
        //向this添加属性和方法
        this.name = name;
        this.say = function(){
            return "I am " + this.name;
        };
        //return this;          
    }      
    

    4、Apply调用模式
    因为Javascript是一门函数式的面向对象编程语言,所以函数可以拥有方法。apply方法让我们构建一个参数数组传递给调用函数,它允许我们选择this的值。apply方法接收两个参数,第一个要绑定给this的值,第二个就是参数数组。
    对于apply和call两者作用上是相同的,但两者在参数上有区别的。对于第一个参数意义都一样,但对第二个参数:apply传入的是一个参数数组,也就是将多个参数组合成一个数组传入,而call则作为call的参数传入(从第二个参数开始)。
    如func.call(func1,var1,var2,var3)对应的apply写法为:func.apply(func1,[var1,var2,var3]);

Fork me on GitHub