`
luozhonghua2014
  • 浏览: 62416 次
文章分类
社区版块
存档分类
最新评论

javascript设计模式理论和示例深入分析(下)

 
阅读更多
6.2.4 组合使用构造函数模式和原型模式(解决原型模式中引用类型值不能的实例不能私有化问题)

创建自定义类型的最常见方式,就是组合使用构造函数模式与原型模式。构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。结果,每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用,最大限度地节省了内存。另外,这种混成模式还支持向构造函数传递参数;可谓是集两种模式之长。下面的代码重写了前面的例子。


function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Shelby", "Court"];
}
Person.prototype = {
constructor : Person,
sayName : function(){
alert(this.name);
}
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Count,Van"
alert(person2.friends); //"Shelby,Count"
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true

在这个例子中,实例属性都是在构造函数中定义的,而由所有实例共享的属性 constructor 和方法 sayName() 则是在原型中定义的。而修改了 person1.friends (向其中添加一个新字符串) ,并不会影响到 person2.friends ,因为它们分别引用了不同的数组。这种构造函数与原型混成的模式,是目前在 ECMAScript中使用最广泛、认同度最高的一种创建自定义类型的方法。可以说,这是用来定义引用类型的一种默认模式。


6.2.5 动态原型模式

有其他 OO 语言经验的开发人员在看到独立的构造函数和原型时,很可能会感到非常困惑。动态原型模式正是致力于解决这个问题的一个方案,它把所有信息都封装在了构造函数中,而通过在构造函数中初始化原型(仅在必要的情况下) ,又保持了同时使用构造函数和原型的优点。换句话说,可以通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型。来看一个例子。


function Person(name, age, job){
//属性
this.name = name;

this.age = age;

this.job = job;

// 方法
if (typeof this.sayName != "function"){
Person.prototype.sayName = function(){
alert(this.name);
};
}

}
var friend = new Person("Nicholas", 29, "Software Engineer");
friend.sayName();

注意构造函数代码中加粗的部分。这里只在 sayName() 方法不存在的情况下,才会将它添加到原型中。这段代码只会在初次调用构造函数时才会执行。此后,原型已经完成初始化,不需要再做什么修改了。不过要记住,这里对原型所做的修改,能够立即在所有实例中得到反映。因此,这种方法确实可以说非常完美。其中, if 语句检查的可以是初始化之后应该存在的任何属性或方法——不必用一大堆if 语句检查每个属性和每个方法;只要检查其中一个即可。对于采用这种模式创建的对象,还可以使用 instanceof 操作符确定它的类型。使用动态原型模式时,不能使用对象字面量重写原型。前面已经解释过了,如果在已经创建了实例的情况下重写原型,那么就会切断现有实例与新原型之间的联系。


6.2.6 寄生构造函数模式
通常,在前述的几种模式都不适用的情况下,可以使用寄生(parasitic)构造函数模式。这种模式的基本思想是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象;但从表面上看,这个函数又很像是典型的构造函数。下面是一个例子。


function Person(name, age, job){
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
alert(this.name);
};
return o;
}
var friend = new Person("Nicholas", 29, "Software Engineer");
friend.sayName(); //"Nicholas"

在这个例子中, Person 函数创建了一个新对象,并以相应的属性和方法初始化该对象,然后又返回了这个对象。 除了使用 new 操作符并把使用的包装函数叫做构造函数之外, 这个模式跟工厂模式其实是一模一样的。构造函数在不返回值的情况下,默认会返回新对象实例。而通过在构造函数的末尾添加一个 return 语句,可以重写调用构造函数时返回的值。这个模式可以在特殊的情况下用来为对象创建构造函数。 假设我们想创建一个具有额外方法的特殊数组。由于不能直接修改 Array 构造函数,因此可以使用这个模式。


function SpecialArray(){
//创建数组
var values = new Array();
//添加值
values.push.apply(values, arguments); //call 以参数表来接受被调用函数的参数
//添加方法
values.toPipedString = function(){
return this.join("|");
};
//返回数组
return values;
}
var colors = new SpecialArray("red", "blue", "green");
alert(colors.toPipedString()); //"red|blue|green"

在这个例子中,我们创建了一个名叫 SpecialArray 的构造函数。在这个函数内部,首先创建了一个数组,然后 push() 方法(用构造函数接收到的所有参数)初始化了数组的值。随后,又给数组实例添加了一个 toPipedString() 方法,该方法返回以竖线分割的数组值。最后,将数组以函数值的形式返回。接着,我们调用了 SpecialArray 构造函数,向其中传入了用于初始化数组的值,此后又调用了 toPipedString() 方法。关于寄生构造函数模式,有一点需要说明:首先,返回的对象与构造函数或者与构造函数的原型属
性之间没有关系;也就是说,构造函数返回的对象与在构造函数外部创建的对象没有什么不同。为此,不能依赖 instanceof 操作符来确定对象类型。 由于存在上述问题, 我们建议在可以使用其他模式的情况下,不要使用这种模式。

6.2.7 稳妥构造函数模式
道格拉斯·克罗克福德(Douglas Crockford)发明了 JavaScript 中的稳妥对象(durable objects)这个概念。所谓稳妥对象,指的是没有公共属性,而且其方法也不引用 this 的对象。稳妥对象最适合在一些安全的环境中 (这些环境中会禁止使用 this 和 new ) , 或者在防止数据被其他应用程序 (如 Mashup程序)改动时使用。稳妥构造函数遵循与寄生构造函数类似的模式,但有两点不同:一是新创建对象的实例方法不引用 this ;二是不使用 new 操作符调用构造函数。按照稳妥构造函数的要求,可以将前面
的 Person 构造函数重写如下。


function Person(name, age, job){
//创建要返回的对象
var o = new Object();

//可以在这里定义私有变量和函数
//添加方法
o.sayName = function(){
alert(name);
};
//返回对象
return o;
}
注意, 在以这种模式创建的对象中, 除了使用 sayName() 方法之外, 没有其他办法访问 name 的值。可以像下面使用稳妥的 Person 构造函数。
var friend = Person("Nicholas", 29, "Software Engineer");
friend.sayName(); //"Nicholas"
这样,变量 friend 中保存的是一个稳妥对象,而除了调用 sayName() 方法外,没有别的方式可以访问其数据成员。即使有其他代码会给这个对象添加方法或数据成员,但也不可能有别的办法访问传入到构造函数中的原始数据。稳妥构造函数模式提供的这种安全性,使得它非常适合在某些安全执行环境——例如,ADsafe(www.adsafe.org)和 Caja(http://code.google.com/p/google-caja/)提供的环境——下使用。


分享到:
评论

相关推荐

    Javascript 设计模式系统讲解与应用

    通过以上分析可以看出,《JavaScript设计模式系统讲解与应用》不仅提供了理论上的指导,还包含了丰富的实际操作案例。这对于想要提升自己JavaScript编程能力的前端开发者来说是非常有价值的资源。掌握这些设计模式...

    常用的Javascript设计模式.pdf

    ### 常用的Javascript设计模式 #### 一、单例模式详解 单例模式是一种常用的软件设计模式,它的核心思想在于确保一个类只有一个实例,并提供一个全局访问点。这种模式在JavaScript这样的“无类”语言中尤为重要。...

    Learning JavaScript Design Patterns[学习javascript设计模式]

    ### 学习JavaScript设计模式 #### 一、引言与背景 在软件开发领域,设计模式作为解决常见问题的一种可重用解决方案,不仅能够帮助开发者借鉴前人的经验,还能够确保代码结构达到最优状态,更好地满足解决问题的...

    javascript 设计模式

    在"JavaScript设计模式.pdf"这个文档中,读者可以找到更深入的分析和实例,了解如何在实际项目中应用这些设计模式,从而提升自己的编程技能。通过学习和实践这些模式,你将能够更好地应对复杂项目的挑战,编写出更加...

    JavaScript高级程序设计第四版-示例代码

    《JavaScript高级程序设计》是JavaScript编程领域的一本经典著作,其第四版更是涵盖了现代JavaScript的诸多新特性。这本书深入探讨了JavaScript的核心概念、语法以及在Web开发中的应用,旨在帮助开发者提升...

    javascript 经典面向对象设计

    《Object-Oriented JavaScript》这本书不仅深入介绍了面向对象编程的基础理论,还提供了大量的实际代码示例和最佳实践指导。对于希望提高JavaScript开发技能、编写出高质量、可扩展和可重用代码的开发者来说,这本书...

    Learning JavaScript Design Pattern

    《Learning JavaScript Design Patterns》是由Addy Osmani撰写的一本专注于JavaScript设计模式的书籍。在这本书中,作者不仅探讨了传统和现代的设计模式,而且还深入分析了这些模式在JavaScript语言中的应用。对于...

    PPK谈javascript示例

    在JavaScript编程领域,PPK(Peter-Paul Koch)是一位知名专家,他的著作《PPK谈JavaScript》深入浅出地介绍了JavaScript的核心概念和技术。本部分将分析提供的代码示例,主要涉及两个方面:文本输入区的长度限制和...

    网站设计 示例 网站

    通过“示例网站”这个压缩包,初学者可以观察和分析不同设计的实现,从中学习到实际的设计技巧和代码实践。每个示例都可能包含上述提到的一个或多个知识点,通过解构和模仿,初学者可以逐步提升自己的设计能力。 ...

    JavaScript 学习脚本

    接下来,我们谈谈JavaScript设计模式。设计模式是解决特定问题的成熟方案,是软件开发中的最佳实践。在JavaScript中,常见的设计模式有: 1. 单例模式:确保一个类只有一个实例,并提供一个全局访问点。 2. 工厂...

    JavaScript 高级程序设计(第3版)【附源代码】

    11. **源码分析**:附带的源代码可以帮助读者更好地理解书中的示例和实践,加深对JavaScript的理解。 通过阅读《JavaScript高级程序设计(第3版)》,开发者不仅可以掌握JavaScript的基本用法,还能深入理解其内部...

    JavaScript+jQuery程序设计 源码

    通过分析和实践这个"JavaScript+jQuery程序设计 源码",学习者不仅能巩固JavaScript和jQuery的基础知识,还能提升实际项目开发经验,尤其是处理网页交互和动态效果的能力。同时,这也将有助于理解和应用更多高级特性...

    设计模式java源码-JavaScript-Design-Patterns:JavaScript设计模式Udacity课程的源代码

    这个压缩包“设计模式java源码 - JavaScript-Design-Patterns”包含了用于讲解JavaScript设计模式的Udacity在线课程的源代码。这个课程的目标是帮助开发者理解和应用各种设计模式,提升他们的编程技能和代码质量。 ...

    15.设计模式面试真题-31页.7z

    在IT行业中,设计模式是软件开发中的重要概念,它代表了在特定场景下解决常见问题的最佳实践。在前端领域,尤其是对于JavaScript、TypeScript以及...因此,对前端开发者来说,深入理解和熟练运用设计模式是至关重要的。

    深入理解JavaScript系列

    Module模式是一种广泛使用的JavaScript设计模式,用于封装代码,避免全局命名空间的污染。 - **Module模式的原理**: - **私有变量与函数**:通过IIFE(Immediately Invoked Function Expression,立即执行函数...

    Pro JavaScript Techniques(jQuery之父作品:精通Javascript英文原版+源码)

    5. **JavaScript设计模式**:讨论常见的面向对象设计模式,如工厂模式、单例模式、观察者模式等,帮助开发者写出更高效、可维护的代码。 6. **性能优化**:探讨如何编写高性能的JavaScript代码,包括避免阻塞渲染、...

    JSP+Servlet+AJAX的dao设计模式

    本篇我们将深入探讨如何在JSP、Servlet和AJAX的环境中应用DAO设计模式。 **1. JSP (JavaServer Pages)** JSP是Java的一种视图技术,用于生成动态网页。在JSP中,我们可以直接编写HTML,同时插入Java代码来处理业务...

    javascript资料(源码,教材,ppt)

    通过阅读和分析这些源码,你可以深入理解JavaScript的实际运用,学习如何编写高效、可维护的代码,同时也能了解到一些最佳实践和常见设计模式。 教材部分通常会提供系统的JavaScript学习指南,包括基础语法、数据...

    JavaScript前端开发案例教程-源代码.rar

    总之,"JavaScript前端开发案例教程-源代码.rar"提供了一个全面学习和实践JavaScript前端开发的平台,通过分析和运行这些源代码,你不仅可以巩固基础知识,还能了解前沿技术,提升自己的开发能力。建议按照文件的...

Global site tag (gtag.js) - Google Analytics