JavaScript方法的4中调用方式

转载自 https://harttle.land/2016/02/03/js-function-invocation.html

函数(Function)是JavaScript的基本模块单元,JavaScript的代码重用, 信息隐藏,对象组合等都可以借助函数来实现。

调用模式

我们知道在函数里可见的名称包括:函数体内声明的变量、函数参数、来自外部的闭包变量。 此外还有两个:this和arguments。
this 在面向对象程序设计中非常重要,而它的值在JavaScript中取决于调用模式。 JavaScript中的函数有4种调用模式:方法调用、函数调用、构造函数调用、apply调用。
arguments 是一个类数组变量(array like),拥有length属性并可以取下标, 它存着所有参数构成的有序数组。 在JavaScript中,函数调用与函数签名不一致(个数不正确、类型不正确定) 时不会产生运行时错。少了的参数会被置为undefined,多了的参数会被忽略。

JavaScript中的函数有4种调用模式:
  • 方法调用(Method Invocation Pattern)
  • 函数调用(Function Invocation Pattern)
  • 构造函数调用(Constructor Invocation Pattern)
  • apply调用(Apply Invocation Pattern)

方法调用

在面向对象程序设计中,当函数(Function)作为对象属性时被称为方法(Method)。 方法被调用时this会被绑定到对应的对象。在JavaScript中有两种语法可以完成方法调用: a.func()和a['func']()。

var obj = {
    val: 0,
    count: function(){
        this.val ++;
        console.log(this.val);
    }
};
obj.count();    // 1
obj.count();    // 2

值得注意的是,this到obj的绑定属于极晚绑定(very late binding), 绑定发生在调用的那一刻。这使得JavaScript函数在被重用时有极大的灵活性。

函数调用

当函数不是对象属性时,它就会被当做函数来调用,比如add(2,3)。 此时this绑定到了全局对象global。

其实this绑定到global是JavaScript的一个设计错误(可以说是最严重的错误), 它导致了对象方法不能直接调用内部函数来做一些辅助工作, 因为内不函数里的this的绑定到了global。 所以如果要重新设计语言,方法调用的this应该绑定到上一级函数的this。

然而共有方法总是需要调用内部辅助函数,于是产生了这样一个非常普遍的解决方案:

man.live= function(){
    var self = this;
    function eat(){
        self.happy++;
    }
    function sleep(){
        self.happy--;
    }
    eat() && sleep();
}

有些场景下用Function.prototype.bind会更加方便:

man.live= function(){
    function eat(apple, rice, ...){
        this.happy++;
    }
    eat.bind(this)();
    ...
}

构造函数调用

JavaScript中,那些用来new对象的函数称为构造函数。

JavaScript采用原型继承方式。这意味着一个对象可以从另一个对象直接继承属性, JavaScript是class free的~ 但JavaScript为了迎合主流的基于类声明的继承方式, 同时也给出了构造函数机制:使用new关键字,便会创建一个对象, 根据prototype属性创建原型链,并以该对象为this执行指定的(构造)函数。

function Man(name, age){
    this.sex = 'man';
    this.name = name;
    this.age = age;
}
Man.prototype.funcAAA = function(apple, rice, ...){}
var man = new Man();
man.funcAAA ();

当构造函数有很多参数时,它们的顺序很难记住,所以通常使用对象进行传参:

var man = new Man({
    name: 'bob',
    age: 18
});

给参数起名字以达到顺序无关的做法在Python中也存在,但JavaScript的对象传参还将带来另一个好处: JSON兼容。因为JavaScript常常需要数据库(例如MongoDB)或网络(application/json)传来的JSON数据,这一点使得对象构造非常方便。

apply调用

JavaScript函数是一种特殊的对象,而对象可以有属性和方法。 其中的apply方法提供了一个更加特殊的调用方式。 它接受两个参数:第一个是该函数要绑定的this,第二个是参数数组。

var args = [apple1, apple2];
var animal = new Animal();
Man.prototype.eat.apply(animal, args);

Apply使得一个方法可以用不同的对象来调用,比如animal也可以用Man的方式来eat。

你可能感兴趣的:(JavaScript方法的4中调用方式)