面向对象的JavaScript --- 动态类型语言


动态类型语言与面向接口编程

JavaScript 没有提供传统面向对象语言中的类式继承,而是通过原型委托的方式来实现对象与对象之间的继承。

JavaScript 也没有在语言层面提供对抽象类和接口的支持。

正因为存在这些跟传统面向对象语言不一致的地方,我们在用设计模式编写代码的时候,更要跟传统面向对象语言加以区别。我们有必要先了解一些 JavaScript 在面向对象方面的知识。

编程语言按照数据类型大体可以分为两类,一类是静态类型语言,另一类是动态类型语言。

静态类型语言在编译时便已确定变量的类型,而动态类型语言的变量类型要到程序运行的时候,待变量被赋予某个值之后,才会具有某种类型。

静态类型语言的优点:

  1. 在编译时就能发现类型不匹配的错误,编辑器可以帮助我们提前避免程序在运行期间有可能发生的一些错误。

  2. 如果在程序中明确地规定了数据类型,编译器还可以针对这些信息对程序进行一些优化工作,提高程序执行速度。

静态类型语言的缺点:

  1. 迫使程序员依照强契约来编写程序,为每个变量规定数据类型,归根结底只是辅助我们编写可靠性高程序的一种手段,而不是编写程序的目的,毕竟大部分人编写程序的目的是为了完成需求交付生产。

  2. 类型的声明也会增加更多的代码,在程序编写过程中,这些细节会让程序员的精力从思考业务逻辑上分散开来。

动态类型语言的优点:

  编写的代码数量更少,看起来也更加简洁,程序员可以把精力更多地放在业务逻辑上面。虽然不区分类型在某些情况下会让程序变得难以理解,但整体而言,代码量越少,越专注于逻辑表达,对阅读程序是越有帮助的。

动态类型语言的缺点:

  无法保证变量的类型,从而在程序的运行期有可能发生跟类型相关的错误。这好像在商店买了一包牛肉辣条,但是要真正吃到嘴里才知道是不是牛肉味。

在 JavaScript 中,当我们对一个变量赋值时,显然不需要考虑它的类型,因此,JavaScript是一门典型的动态类型语言。动态类型语言对变量类型的宽容给实际编码带来了很大的灵活性。由于无需进行类型检测,我们可以尝试调用任何对象的任意方法,而无需去考虑它原本是否被设计为拥有该方法。

这一切都建立在鸭子类型(duck typing)的概念上,通俗说法是:“如果它走起路来像鸭子,叫起来也是鸭子,那么它就是鸭子。 ”

通过一个小故事来更深刻地了解该类型:

从前在 JavaScript 王国里,有一个国王,他觉得世界上最美妙的声音就是鸭子的叫声,于是国王召集大臣,要组建一个 1000 只鸭子组成的合唱团。大臣们找遍了全国,终于找到999只鸭子,但是始终还差一只,最后大臣发现有一只非常特别的鸡,它的叫声跟鸭子一模一样,于是这只鸡就成为了合唱团的最后一员。

这个故事告诉我们,国王要听的只是鸭子的叫声,这个声音的主人到底是鸡还是鸭并不重要。鸭子类型指导我们只关注对象的行为,而不关注对象本身。

用代码来模拟这个故事:

var duck = {
duckSinging: function(){
console.log( '嘎嘎嘎' );
}
};
var chicken = {
duckSinging: function(){
console.log( '嘎嘎嘎' );
}
};
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 --- 动态类型语言的更多相关文章

  1. 【转】解析JDK 7的动态类型语言支持

    http://www.infoq.com/cn/articles/jdk-dynamically-typed-language Java虚拟机的字节码指令集的数量自从Sun公司的第一款Java虚拟机问 ...

  2. Python 语言特性:编译+解释、动态类型语言、动态语言

    1. 解释性语言和编译性语言 1.1 定义 1.2 Python 属于编译型还是解释型? 1.3 收获 2. 动态类型语言 2.1 定义 2.2 比较 2. 动态语言(动态编程语言) 3.1 定义 3 ...

  3. Python基础系列讲解—动态类型语言的特点

    前言 在C语言中变量所分配到的地址是内存空间中一个固定的位置,当我们改变变量值时, 对应内存空间中的值也相应改变.在Python中变量存储的机制是完全不一样的,当给一个变量赋值时首先解释器会给这个值分 ...

  4. 关于"动态语言" "静态语言" "静态类型语言" "动态类型语言"的区别

    参考链接:关于“编译型”“解释型”“动态语言”“静态语言”“动态类型语言”“静态类型语言”的区分以及优缺点(汇总整理) 很多人把这两类混为一谈,但是这是完全不同的两个概念!!! 动态和静态语言主要看的 ...

  5. 解析JDK 7的动态类型语言支持

    http://www.infoq.com/cn/articles/jdk-dynamically-typed-language

  6. 《JavaScript设计模式与开发实践》-面向对象的JavaScript

    设计模式 面向对象 动态类型语言 编程语言按照数据类型大体分为:静态类型语言和动态类型语言. 静态类型语言在编译时便已确定变量的类型,而动态类型语言的变量类型要到程序运行时,待变量被赋予某个值之后,才 ...

  7. 面向对象的JavaScript --- 多态

    面向对象的JavaScript --- 多态 多态 "多态"一词源于希腊文 polymorphism,拆开来看是poly(复数)+ morph(形态)+ism,从字面上我们可以理解 ...

  8. JavaScript设计模式基础之面向对象的JavaScript(一)

    动态语言类型与鸭子类型 此内容取自JavaScript设计模式与开发实践一书 编程语言按照数据类型大体可以分为2类,一类就是静态类型语言,另一类则是动态类型语言 静态类型语言也可以称之为编译语言,而动 ...

  9. 第1章 面向对象的JavaScript

    针对基础知识的每一个小点,我都写了一些小例子,https://github.com/huyanluanyu1989/DesignPatterns.git,便于大家理解,如有疑问,大家可留言给我,最近工 ...

随机推荐

  1. AngularJS学习笔记(四)内置指令

    说说指令 不得不赞叹,指令是ng最为强大的功能之一,好吧,也可以去掉之一,是最强大的功能.ng内置了许多自定义的指令,这避免了我们自己去造轮子.同时,ng也提供了自定义指令的功能,可以让我们的页面元素 ...

  2. Spring基础(6) : 普通Bean对象中保存ApplicationContext

    public class Person implements ApplicationContextAware{ ApplicationContext context; public String na ...

  3. Join 具体用法

    一.Join 语法概念 Join 按照功能可分为三大类: left join (左连接) 即:取左边表的全部数据,即使右边表没有对应的数据,也是会把左边表的数据取出来,并返回 right join(右 ...

  4. Killing Monsters(hdu4970)

    Killing Monsters Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)T ...

  5. JAVA设计模式详解(五)----------适配器模式

    各位朋友好,本章节我们继续讲第五个设计模式. 在生活中,我们都知道手机内存卡是无法直接接电脑的,因为内存卡的卡槽比较小,而电脑只有USB插孔,此时我们需要用到读卡器.这个读卡器就相当于是适配器.这是生 ...

  6. spring-bean实例化三种方式

    在spring中,bean的示例化有三种方式. 1.使用类的无参构造函数创建 2.使用静态工厂方式创建 3.使用实例化工厂方式创建. 具体代码如下 静态工厂方式: Bean2.java package ...

  7. Codeforces841A

    A. Generous Kefa time limit per test:2 seconds memory limit per test:256 megabytes input:standard in ...

  8. Sql Server分页储存过程

    --分页储存过程if exists (select * from sys.procedures where name='Page')drop proc Pagegocreate proc Page@P ...

  9. js点击获取标签元素

     14.数组去重 方法一:利用冒泡 function elementName(evt){ evt = evt|| window.event; // IE: window.event // IE用src ...

  10. CSS 关于屏幕适配REM

    这里不多说了,想详细了解的可以参考 2350305682 的博客 https://www.cnblogs.com/annie211/p/8118857.html 不想多深究,想先实现的看这(移动端): ...