博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Javascript 构造函数模式、原型模式
阅读量:4640 次
发布时间:2019-06-09

本文共 3080 字,大约阅读时间需要 10 分钟。

前两天写完组合继承,打算总结一下原型继承的,不过今天看了一下工厂模式、构造函数模式和原型模式,觉得有必要总结一下以加深印象。

——————————————————————————————————————————————————————————————————————————————————碎碎念。

1.工厂模式

《Javascript 高级程序设计(第3版)》 用了寥寥十多行介绍了工厂模式。我找了一些相关资料,想确定一下这种模式的具体适用场景和优势。按照资料中的说法,是考虑到 ECMAScript 无法创建类,所以:

创建一个对象,紧接着描述对象的属性和方法,最后用另一个对象把它们封装起来当作接口。

按照上面描述的,工厂函数是用来在 Javascript 中实现类似于 Java 中类的功能。通过调用工厂函数,可以创建多个相似的对象实例。

    简单工厂模式:使用一个类(通常为单体)来生成实例。

    复杂工厂模式:使用子类来决定一个成员变量应该是哪个具体的类的实例。

关于 Javascript 使用工厂模式的优点,根据网上的总结,大概有以下几点:

a. 消除对象之间的耦合(这个不太明白,消除谁与谁的耦合?);

b. 在进行批次相关设置时,把所有实例化的代码都集中在一个位置,有助于创建模块化的代码,减少代码量;

c.  用于许多小型对象组成一个大对象。

缺点:

a. 没有解决对象识别的问题。

 

.....这个模式先留着吧,没太搞透彻优势在哪。以后领悟了的话再来补充。引用《Javascript 设计模式与开发实践》P5中的一段话:

“而在 Javascript 这种类型模糊的语言中,对象多态性是天生的,一个变量既可以指向一个类,又可以随时指向另外一个类。Javascript 不存在类型耦合问题,自然也没有必要刻意把对象“延迟”到子类创建,也就是说,Javascript 实际上是不需要工厂方法模式的。 模式的存在首先是能为我们解决什么问题,这种牵强的模拟只会让人觉得设计模式既难懂又没什么用。”

2. 构造函数模式

关于封装: 在 Javascript 中,可以将一些属性和方法封装到构造函数内;

关于多态:在 Javascript 中不存在重载的概念,但可以通过参数个数和类型判断来模拟重载,但是 Javascript 中多态是与生俱来的。一个最简单的栗子:

同一个构造函数实例化得到的两个对象实例,可以给它们传入不同的参数,这两个对象实例是不同的。这就是面向对象编程的多态。

利用构造函数模式,可以创建多个实例,这些实例都被标定为了特定的类型。构造函数模式相比于工厂模式更为简单且易于实现,但也存在缺点:

function Person(name,age,job){    this.name = name;    this.age = age;    this.job = job;    this.arr = [];    this.sayName = function(){        alert(this.name);    };}var person1 = new Person("Nicholas",29,"Software Engineer");var person2 = new Person("Greg",27,"Doctor");console.log(person1.sayName==person2.sayName);//falseperson1.arr.push(1);console.log(person1.arr);//1person2.arr.push(2);console.log(person2.arr);//2

利用构造函数每实例化一个实例对象,构造函数内的方法都要在实例上重新创建一次。通过 person1.sayName==person2.sayName 返回的返回结果可以看到两个实例引用的方法是不同的。

注意:这一点也适用于数组。

可以通过将构造函数的方法放在外部,使得对象实例每次都引用同一个方法。

function Person(name,age,job){    this.name = name;    this.age = age;    this.job = job;    this.sayName = sayName;}function sayName(){        alert(this.name);}var person1 = new Person("Nicholas",29,"Software Engineer");var person2 = new Person("Greg",27,"Doctor");console.log(person1.sayName==person2.sayName);//true

通过将构造函数的方法提到外部作为:特权方法。可以使实例获得相同的方法引用。

但是这种方法也存在一些问题:将方法提到外部作为特权方法使得封装性变差。如果构造函数内部有很多个方法,这样做后果更为明显。

另外再看一个问题:如果构造函数内有多个固定属性,并且存在多个方法。实例化的时候要为每个对象都复制相同的固定属性,如果将方法放在构造函数内部,这些方法也要复制,即使都作为特权函数,也存在弊端。

总结,构造函数模式存在两点不足:1. 浪费内存;2. 可能会使封装性变差。

3.原型模式

原型模式的出现,解决了构造函数实例化过程中对固定属性个方法重复深复制的问题。

对于相同的属性和方法,只要在构造函数的原型对象上申明一次,构造函数的实例就可以共享同一个属性和方法。

function Person(){}Person.prototype.name = "Nicholas";Person.prototype.sayName = function(){    console.log(this.name);}var person1 = new Person();var person2 = new Person();console.log(person1.sayName===person2.sayName);//trueconsole.log(person1.name===person2.name);//true

 4.组合使用构造函数模式和原型模式(混合模式)

但是可以看到,虽然原型模式能够解决固定属性和方法多次复制的问题,如果属性要根据不同实例对象改变,这时候最好还是把会随实例对象改变的属性放置在构造函数内部,这又用到了构造函数模式。将构造函数模式和原型模式相结合,就能利用这两个模式的优势。

function Person(name,age){    //会随实例对象改变的属性    this.name = name;    this.age = age;}//不变的属性或者是方法Person.prototype.job = "Soft Engineer";Person.prototype.sayName = function(){    console.log(this.name);}var person1 = new Person("Nicholas",28);var person2 = new Person("Shelby",25);

 

转载于:https://www.cnblogs.com/tisikcci/p/5846844.html

你可能感兴趣的文章
ubuntun 服务器与Mac
查看>>
重温JSP学习笔记--与日期数字格式化有关的jstl标签库
查看>>
java-Date-DateFormat-Calendar
查看>>
封装CLLocationManager定位获取经纬度
查看>>
我的第一篇博客-(Eclipse中或Myeclipse中如果不小心删除了包那可怎么办?)
查看>>
对easyui datagrid组件的一个小改进
查看>>
类似以下三图竞争关系的IT企业
查看>>
Qt5启动画面
查看>>
清明节
查看>>
谈谈一些有趣的CSS题目(七)-- 消失的边界线问题
查看>>
ubuntu如何安装svn客户端?
查看>>
arcgis for javascript (3.17)
查看>>
【MySQL】Win7下修改MySQL5.5默认编码格式
查看>>
AI之路,第二篇:python数学知识2
查看>>
windows10关闭更新,windowsUpdate禁用无效 windows无限重启 一分钟无限重启 win10无法连接到SENS服务...
查看>>
[LeetCode] Alien Dictionary
查看>>
[LintCode] 空格替换
查看>>
JSSDK微信支付封装的支付类方法,代码比较齐全,适合收藏
查看>>
Java线程及Jvm监控工具
查看>>
Blutooth MESH
查看>>