本文是《javascript设计模式与开发实践》一书学习笔记,因书中所表述的概念简单明了,故将整本书的笔记奉上,所有文章大概在20篇左右,还请朋友们持续关注javascript
编程语言按照数据类型大致能够分为两类,一类是静态类型语言,另外一类是动态类型语言java
静态类型语言,声明任何变量或者形参都须要指定类型,例如java语言。
动态类型语言,声明任何变量或者形参都不须要指定类型,javascript就是动态类型语言。编程
所谓动态,能够多层面的理解,首先,声明变量不须要指定类型,其次,在多态思想下,java中须要利用父类实现多态,而javascript就不须要,自己自带多态属性。设计模式
熟悉java的朋友知道,java三大特征之一就有多态,多态给java带来了很大的灵活性,不少设计模式也是经过多态来实现,java中的多态涉及到向上转型和向下转型,而javascript(如下简称js)的"多态"就相对来讲容易实现安全
咱们来看一段“多态”的js代码编程语言
var makeSound = function(an) { if(an instanceof Duck) { console.log("嘎嘎嘎"); } else if(an instanceof Dog) { console.log("汪汪汪"); } } var Dog = function(){}; var Duck = function(){}; makeSound(new Dog()); makeSound(new Duck());
这段代码确实体现了“多态性”,当咱们分别向鸭和鸡发出“叫唤”的消息时,它们根据此 消息做出了各自不一样的反应,可是这样写会有一个弊端,当更多的类型出现时,咱们要不断的修改makeSound函数,后期makeSound函数也会变得十分巨大,这不符合良好代码设计的规范,多态背后的思想是将“作什么”和“谁去作以及怎样去作”分离开来,也就是将“不变的事 物”与 “可能改变的事物”分离开来。在这个故事中,动物都会叫,这是不变的,可是不一样类 型的动物具体怎么叫是可变的。把不变的部分隔离出来,把可变的部分封装起来,这给予了咱们 扩展程序的能力,程序看起来是可生长的,也是符合开放—封闭原则的,相对于修改代码来讲, 仅仅增长代码就能完成一样的功能,这显然优雅和安全得多函数
首先,咱们把makeSound函数修改一下:学习
var makeSound = function(an) { an.speak(); }
这段代码传入一个对象,而后调用对象的speak函数prototype
var Duck = function(){} Duck.prototype.sound = function(){ console.log( '嘎嘎嘎' ); }; var Chicken = function(){} Chicken.prototype.sound = function(){ console.log( '咯咯咯' ); }; makeSound( new Duck() ); // 嘎嘎嘎 makeSound( new Chicken() );
如今咱们向鸭和鸡都发出“叫唤”的消息,它们接到消息后分别做出了不一样的反应。若是有 一天动物世界里又增长了一只狗,这时候只要简单地追加一些代码就能够了,而不用改动之前的 makeSound 函数设计
如今,咱们来进一步了解多态,以前说到,java的多态须要利用继承来实现,咱们如今把动物的例子换成java代码
public class Duck { public void speak(){ System.out.println( "嘎嘎嘎" ); } } public class Dog { public void speak(){ System.out.println( "汪汪汪" ); } } public class AnimalSpeak{ public void makeSound(Duck duck){ duck.speak(); } } public static void main(String args[]){ AnimalSpeak an = new AnimalSpeak(); Duck duck = new Duck(); an.makeSound(duck); // 输出:嘎嘎嘎 }
如今鸭子已经顺利叫出来了,可是咱们想让狗也叫,发现不太容易实现,由于makeSound函数中,形参是Duck类型,传入Dog类型必定会报错,这个时候继承就出现了,java设计思路是我先建立一个父类,具体传入的类型由子类决定,可是makeSound函数中的形参确是父类类型,实现以下:
public abstract class Animal{ abstract void speak(); // 抽象方法 } public class Duck extends Animal { public void speak(){ // 覆写父类中的抽象方法 System.out.println( "嘎嘎嘎" ); } } public class Dog extends Animal { public void speak(){ // 覆写父类中的抽象方法 System.out.println( "汪汪汪" ); } } public class AnimalSpeak{ public void makeSound(Animal an){ an.speak(); } } public static void main(String args[]){ AnimalSpeak an = new AnimalSpeak(); Animal duck = new Duck(); Animal dog = new Dog(); an.makeSound(duck); // 输出:嘎嘎嘎 an.makeSound(dog); // 输出:汪汪汪 }
JavaScript 对象的多态性是与生俱来的,为何这么说? 仔细看看这两个函数:
public void makeSound(Animal an){ an.speak(); } function(an) { an.speak(); }
js和java中的函数的形参是不一样的,java定死了传入的类型,而js是动态的,js随即可以传入任何类型,因此,咱们以前说js是动态类型语言,在 JavaScript 这种将函数做为一等对象的语言中,函数自己也是对象,函数用来封装行为并 且可以被四处传递。当咱们对一些函数发出“调用”的消息时,这些函数会返回不一样的执行结 果,这是“多态性”的一种体现,也是不少设计模式在 JavaScript 中能够用高阶函数来代替实现的缘由。