- 编程语言按照数据类型大体可以分为两类,一类是静态类型语言,另一类是动态类型语言。
静态类型语言在编译时便已确定变量的类型,而动态类型语言的变量类型要到程序运行的时
候,待变量被赋予某个值之后,才会具有某种类型。
- 静态类型语言的优点首先是在编译时就能发现类型不匹配的错误,编辑器可以帮助我们提前
避免程序在运行期间有可能发生的一些错误。其次,如果在程序中明确地规定了数据类型,编译
器还可以针对这些信息对程序进行一些优化工作,提高程序执行速度。
- 静态类型语言的缺点首先是迫使程序员依照强契约来编写程序,为每个变量规定数据类型,
归根结底只是辅助我们编写可靠性高程序的一种手段,而不是编写程序的目的,毕竟大部分人编
写程序的目的是为了完成需求交付生产。其次,类型的声明也会增加更多的代码,在程序编写过
程中,这些细节会让程序员的精力从思考业务逻辑上分散开来。
- 动态类型语言的优点是编写的代码数量更少,看起来也更加简洁,程序员可以把精力更多地
放在业务逻辑上面。虽然不区分类型在某些情况下会让程序变得难以理解,但整体而言,代码量
越少,越专注于逻辑表达,对阅读程序是越有帮助的。
- 动态类型语言的缺点是无法保证变量的类型,从而在程序的运行期有可能发生跟类型相关的
错误。这好像在商店买了一包牛肉辣条,但是要真正吃到嘴里才知道是不是牛肉味。
在 JavaScript 中,当我们对一个变量赋值时,显然不需要考虑它的类型,因此,JavaScript
是一门典型的动态类型语言。
- 动态类型语言对变量类型的宽容给实际编码带来了很大的灵活性。由于无需进行类型检测,
我们可以尝试调用任何对象的任意方法,而无需去考虑它原本是否被设计为拥有该方法。
这一切都建立在鸭子类型(duck typing)的概念上,鸭子类型的通俗说法是:“如果它走起
路来像鸭子,叫起来也是鸭子,那么它就是鸭子。”
我们可以通过一个小故事来更深刻地了解鸭子类型。
从前在 JavaScript 王国里,有一个国王,他觉得世界上最美妙的声音就是鸭子的叫
声,于是国王召集大臣,要组建一个 1000 只鸭子组成的合唱团。大臣们找遍了全国,
终于找到 999 只鸭子,但是始终还差一只,最后大臣发现有一只非常特别的鸡,它的叫
声跟鸭子一模一样,于是这只鸡就成为了合唱团的最后一员。
这个故事告诉我们,国王要听的只是鸭子的叫声,这个声音的主人到底是鸡还是鸭并不重要。
鸭子类型指导我们只关注对象的行为,而不关注对象本身,也就是关注 HAS-A, 而不是 IS-A。
下面我们用代码来模拟这个故事。
`var duck = {
duckSinging: function(){
console.log( '嘎嘎嘎' );
}
};
var chicken = {
duckSinging: function(){
console.log( '嘎嘎嘎' ); Version:0.9 StartHTML:0000000105 EndHTML:0000002703 StartFragment:0000000141 EndFragment:0000002663
}
};
var choir = []; // 合唱团
var joinChoir = function( animal ){
if ( animal && typeof animal.duckSinging === 'function' ){
choir.push( animal );
console.log( '恭喜加入合唱团' );
console.log( '合唱团已有成员数量:' + choir.length );
}
};
joinChoir( duck ); // 恭喜加入合唱团
joinChoir( chicken ); // 恭喜加入合唱团`
- 我们看到,对于加入合唱团的动物,大臣们根本无需检查它们的类型,而是只需要保证它们
拥有 duckSinging 方法。如果下次期望加入合唱团的是一只小狗,而这只小狗刚好也会鸭子叫,
我相信这只小狗也能顺利加入。
- 在动态类型语言的面向对象设计中,鸭子类型的概念至关重要。利用鸭子类型的思想,我们
不必借助超类型的帮助,就能轻松地在动态类型语言中实现一个原则:“面向接口编程,而不是
面向实现编程”。例如,一个对象若有 push 和 pop 方法,并且这些方法提供了正确的实现,它就
可以被当作栈来使用。一个对象如果有 length 属性,也可以依照下标来存取属性(最好还要拥
有 slice 和 splice 等方法),这个对象就可以被当作数组来使用。
- 在静态类型语言中,要实现“面向接口编程”并不是一件容易的事情,往往要通过抽象类或
者接口等将对象进行向上转型。当对象的真正类型被隐藏在它的超类型身后,这些对象才能在类
型检查系统的“监视”之下互相被替换使用。只有当对象能够被互相替换使用,才能体现出对象
多态性的价值。
- “面向接口编程”是设计模式中最重要的思想,但在 JavaScript 语言中,“面向接口编程”的
过程跟主流的静态类型语言不一样,因此,在 JavaScript 中实现设计模式的过程与在一些我们熟
悉的语言中实现的过程会大相径庭。
本文引用自 JavaScript设计模式与开发实践 一书