JavaScript 方法的4种调用模式

标签: JavaScript 构造函数 调用模式 | 发表时间:2016-02-03 08:00 | 作者:
出处:http://harttle.com/

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

  • 方法调用(Method Invocation Pattern)
  • 函数调用(Function Invocation Pattern)
  • 构造函数调用(Constructor Invocation Pattern)
  • apply调用(Apply Invocation Pattern)

与其他语言不通,JavaScript的函数是一种特殊的对象 (事实上,JavaScript函数是一级对象)。 这意味着函数可以有属性,可以有方法,也可以传参、返回、赋值给变量、加入数组。 与对象不同的是函数可以被调用。

既然是对象便会有原型。我们知道通过花括号语法创建的对象的原型是 Object.prototype。 通过函数语法( function关键字或 new Function())创建的函数,其原型自然是 Function.prototype。 而 Function.prototype的原型是 Object.prototype

注意上述『原型』指的是原型链上的隐式原型,区别于 prototype原型属性。

调用模式

我们知道在函数里可见的名称包括:函数体内声明的变量、函数参数、来自外部的闭包变量。 此外还有两个: thisarguments

this在面向对象程序设计中非常重要,而它的值在JavaScript中取决于 调用模式。 JavaScript中的函数有4种调用模式:方法调用、函数调用、构造函数调用、apply调用。

arguments是一个类数组变量(array like),拥有 length属性并可以取下标, 它存着所有参数构成的有序数组。 在JavaScript中,函数调用与函数签名不一致(个数不正确、类型不正确定) 时不会产生运行时错。少了的参数会被置为 undefined,多了的参数会被忽略。

方法调用模式

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

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

obj.count();    // 1
obj.count();    // 2

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

函数调用模式

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

在[那些 JavaScript 的优秀特性][elegant-js]一文中曾提到, JavaScript的编译(预处理)需要 global对象来链接所有全局名称。

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

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

   man.love = function(){
    var self = this;
    function fuck(){
        self.happy++;
    }
    function marry(){
        self.happy--;
    }
    fuck() && marry();
}

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

   man.love = function(){
    function fuck(girl1, girl2, ...){
        this.happy++;
    }
    fuck.bind(this)();
    ...
}

构造函数调用模式

Classically inspired syntax obscures the language’s true prototypal natur.

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.fuck = function(girl1, girl2, ...){}
var man = new Man();
man.fuck();

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

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

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

Apply 调用模式

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

   var args = [girl1, girl2];
var animal = new Animal();
Man.prototype.fuck.apply(animal, args);

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

[elegant-js]: {% post_url 2016-01-18-elegant-javascript %}

相关 [javascript 方法 模式] 推荐:

JavaScript 方法的4种调用模式

- - Harttle Land
函数(Function)是JavaScript的基本模块单元,JavaScript的代码重用, 信息隐藏,对象组合等都可以借助函数来实现. JavaScript中的函数有4种调用模式:. 方法调用(Method Invocation Pattern). 函数调用(Function Invocation Pattern).

Javascript 严格模式详解

- - 阮一峰的网络日志
除了正常运行模式,ECMAscript 5添加了第二种运行模式: "严格模式"(strict mode). 顾名思义,这种模式使得Javascript在更严格的条件下运行. 设立"严格模式"的目的,主要有以下几个:.   - 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;.

JavaScript代码复用模式

- - SegmentFault 最新的文章
代码复用,顾名思义就是对曾经编写过的代码的一部分甚至全部重新加以利用,从而构建新的程序. 在谈及代码复用的时候,我们首先可以想到的是 继承性. 优先使用对象组合,而不是类继承. 在js中,由于没有类的概念,因此实例的概念也就没多大意义,js中的对象是简单的键-值对,可以动态的创建和修改它们. 但在 js中,我们可以使用构造函数和 new操作符来实例化一个对象,这与其他使用类的编程语言在语法上有其相似之处.

javascript封装addClass()方法

- - 收集分享互联网资源!
//获取obj标签对象的class. //如果oClass为空则直接赋newClass. //1、判断当前标签里是否含有newClass,如果含有newClass则return跳出不赋值,避免反复赋同样的newClass. //2、如果不含有newClass,则在原来oClass的基础上添加新的newClass.

学习JavaScript的最佳方法

- 黄立 - 译言-每日精品译文推荐
学习JavaScript的最佳方法. Andrew Burgess 2011年9月21日. You don’t have to worry about finding the best resources, sorting out the bad ones, and figuring out what to learn next.

Javascript定义类(class)的三种方法

- - 阮一峰的网络日志
将近20年前, Javascript诞生的时候,只是一种简单的网页脚本语言. 如果你忘了填写用户名,它就跳出一个警告. 如今,它变得几乎无所不能,从前端到 后端,有着各种 匪夷所思的用途. 程序员用它完成越来越庞大的项目. Javascript代码的复杂度也直线上升. 单个网页包含10000行Javascript代码,早就司空见惯.

Javascript异步编程的4种方法

- - 阮一峰的网络日志
你可能知道,Javascript语言的执行环境是"单线程"(single thread). 所谓"单线程",就是指一次只能完成一件任务. 如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推. 这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行.

Javascript网页截屏的方法

- - WebHek
最近我在研究开发一个火狐插件,具体的功能是将网页内容截屏并分享到微博上. 目前基本功能已经实现,大家可以在 @程序师视野 里看到用这个截图插件分享的微博的效果. 之前我曾写过 如何将canvas图形转换成图片和 下载canvas图像的方法,这些都是在为这个插件做技术准备. 技术路线很清晰,将网页的某个区域的内容生成图像,保持到canvas里,然后将canvas内容转换成图片,保存到本地,最后上传到微博.

javascript严谨模式提升开发效率和质量

- - ITeye博客
JavaScript严谨模式(Strict Mode)提升开发效率和质量(转载). 随着WebApp突飞猛进的发展,Javascript写的WebApp规模越来月庞大,比如典型的代表产品. 腾讯WebQQ、HTML5游戏等等,Javascript越来越需要大量的开发人员多多人协作开发. 同时HTML5、CSS3等新技术和NodeJs项目的高速发展,这几年JavaScript语言借着各种新API陆续被运用到从移动设备到服务器的多个”新领域”中.

用javascript预加载图片、css、js的方法研究

- - 博客园_Ruby's Louvre
预加载的好处可以让网页更快的呈现给用户,缺点就是可能会增加无用的请求(但图片、css、js这些静态文件可以被缓存),如果用户访问的页面里面的 css、js、图片被预加载了,用户打开页面的速度会快很多,提升用户体验. 在用到一些大图片展示的时候,预加载大图是很不错的方法,图片更快的被呈现给用户. 不多说了,作为一个前端攻城师都懂的,下面分享我做的测试和得到的结果.