【JavaScript回顾】对象创建的几种模式
组合使用构造函数模式和原型模式
创建自定义类型的常见方式,就是组合使用构造函数模式与原型模式。构造函数模式用于定义实 例属性,而原型模式用于定义方法和共享的属性。结果,每个实例都会有自己的一份实例属性的副本, 但同时又共享着对方法的引用,大限度地节省了内存。另外,这种混成模式还支持向构造函数传递参 数;可谓是集两种模式之长。
<script>
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Shelby", "Sylvia"];
} Person.prototype = {
constructor: Person,
showFriends: function () {
var message = this.name + ":";
this.friends.forEach(function (v, i, array) {
message += " " + v;
});
alert(message); }
} var p1 = new Person("gck", 26, "senior software engineer");
p1.friends.push("Carol");
p1.showFriends(); var p2 = new Person("gck", 26, "senior software engineer");
p2.showFriends();
</script>
在这个例子中,实例属性都是在构造函数中定义的,而由所有实例共享的属性 constructor 和方 法 sayName()则是在原型中定义的。而修改了 person1.friends(向其中添加一个新字符串),并不 会影响到 person2.friends,因为它们分别引用了不同的数组。 这种构造函数与原型混成的模式,是目前在 ECMAScript中使用广泛、认同度高的一种创建自 定义类型的方法。可以说,这是用来定义引用类型的一种默认模式。
动态原型模式
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 操作符确定它的类型。
注:使用动态原型模式时,不能使用对象字面量重写原型。前面已经解释过了,如果 在已经创建了实例的情况下重写原型,那么就会切断现有实例与新原型之间的联系。
寄生构造函数模式
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 构造函数,因此可以使用这个模式。
<script>
function SpecialArray(){
//创建数组
var values = new Array();
//添加值
values.push.apply(values, arguments);
//添加方法
values.toPipedString = function() {
return this.join("|");
};
//返回数组
return values;
}
var colors = new SpecialArray("red", "blue", "green");
alert(colors.toPipedString()); //"red|blue|green"
</script>
在这个例子中,我们创建了一个名叫 SpecialArray 的构造函数。在这个函数内部,首先创建了 一个数组,然后 push()方法(用构造函数接收到的所有参数)初始化了数组的值。随后,又给数组实 例添加了一个 toPipedString()方法,该方法返回以竖线分割的数组值。后,将数组以函数值的形 式返回。接着,我们调用了 SpecialArray 构造函数,向其中传入了用于初始化数组的值,此后又调 用了 toPipedString()方法。 关于寄生构造函数模式,有一点需要说明:首先,返回的对象与构造函数或者与构造函数的原型属 性之间没有关系;也就是说,构造函数返回的对象与在构造函数外部创建的对象没有什么不同。为此, 不能依赖 instanceof 操作符来确定对象类型。由于存在上述问题,我们建议在可以使用其他模式的情 况下,不要使用这种模式。
稳妥构造函数模式
<script>
function Person(name, age, job){
//创建要返回的对象
var o = new Object();
//可以在这里定义私有变量和函数 //添加方法
o.sayName = function(){ alert(name); };
//返回对象
return o;
}
</script>
注意,在以这种模式创建的对象中,除了使用 sayName()方法之外,没有其他办法访问 name 的值。 可以像下面使用稳妥的 Person 构造函数。
var friend = Person("Nicholas", 29, "Software Engineer"); friend.sayName(); //"Nicholas" 这样,变量 friend 中保存的是一个稳妥对象,而除了调用 sayName()方法外,没有别的方式可 以访问其数据成员。即使有其他代码会给这个对象添加方法或数据成员,但也不可能有别的办法访问传 入到构造函数中的原始数据。稳妥构造函数模式提供的这种安全性,使得它非常适合在某些安全执行环境。
注:与寄生构造函数模式类似,使用稳妥构造函数模式创建的对象与构造函数之间也 没有什么关系,因此 instanceof 操作符对这种对象也没有意义。
【JavaScript回顾】对象创建的几种模式的更多相关文章
- OpenJDK源码研究笔记(十三):Javac编译过程中的上下文容器(Context)、单例(Singleton)和延迟创建(LazyCreation)3种模式
在阅读Javac源码的过程中,发现一个上下文对象Context. 这个对象用来确保一次编译过程中的用到的类都只有一个实例,即实现我们经常提到的"单例模式". 今天,特意对这个上下文 ...
- JS对象创建的几种方式整理
本文主要介绍了JS对象创建的几种方式 第一种:Object构造函数创建 var Person = new Object(); Person.name = 'Nike'; Person.age = ...
- JavaScript中的对象-创建对象的7种模式
文章来源:http://blog.csdn.net/u014346301/article/details/52204967 ECMA-262把对象定义为:”无需属性的集合,其属性可以包含基本值.对象或 ...
- JavaScript基础对象创建模式之单体/单例模式(Singleton)
首先,单例模式是对象的创建模式之一,此外还包括工厂模式.单例模式的三个特点: 1,该类只有一个实例 2,该类自行创建该实例(在该类内部创建自身的实例对象) 3,向整个系统公开这个实例接口 Java中大 ...
- JavaScript基础对象创建模式之私有属性和方法(024)
JavaScript没有特殊的语法来表示对象的私有属性和方法,默认的情况下,所有的属性和方法都是公有的.如下面用字面声明的对象: var myobj = { myprop: 1, getProp: f ...
- JavaScript对象创建的几种方式
1 工厂模式 1.1 创建 function createFruit(name,colors) { var o = new Object(); o.name = name; o.colors = co ...
- javascript的对象创建模式---命名空间模式
javascript中对象的概念是很普遍的,对象是是对象,数组是对象,函数也是对象,字符串其实也是对象.常见的对象创建方法有对象字面量.构造函数创建.我们先来看看对象的创建还有哪些更高级的模式. 一. ...
- JavaScript基础对象创建模式之沙盘模式(026)
沙盘模式可以弥补命名空间模式中的两项不足之处: 使用唯一全局对象作为程序的全局变量入口,使得无法在同一程序中使用两个不同版本的API,因此它们使用的是同一个唯一的全局对象名,如MYAPP: 较长的嵌套 ...
- JavaScript基础对象创建模式之链式调用模式(Chaining Pattern)(029)
链式调用模式允许一个接一个地调用对象的方法.这种模式不考虑保存函数的返回值,所以整个调用可以在同一行内完成: myobj.method1("hello").method2().me ...
随机推荐
- JRE_HOME environment variable is not defined correctly This environment variableis needed to run this program
已经安装了JDK1.7 和对应JRE 安装了tomcat8 都是解压版 并设置了JAVA_HOME.JRE_HOME 但Tomcat在启动过程中找不到 错误: the JRE_HOME environ ...
- ARCGIS10.1 GeoDatabase深入理解:客户端连接与退出地理数据库时系统表的初始化
平台软件:ARCIGS10.1 ,SQL Server2008R2 目的:了解客户端在连接arcgis 空间地理数据库后,地理数据库会做些什么样的初始化工作 准备工作: 1.准备好数据库日志文件查看工 ...
- cordova混合开发:Android中native调用javascript
今天学习怎么在java中调用javascript方法,做个记录: 第一种方式,这个最简单: loadUrl("javascript:func1()"); 要注意要在devicere ...
- C++11实现一个自动注册的工厂
实现动机 工厂方法是最简单地创建派生类对象的方法,也是很常用的,工厂方法内部使用switch-case根据不同的key去创建不同的派生类对象,下面是一个伪代码. Message* create(int ...
- 【AI】蒙特卡洛搜索树
http://jeffbradberry.com/posts/2015/09/intro-to-monte-carlo-tree-search/ 蒙特卡洛方法与随机优化: http://iacs-co ...
- Spring AOP Schema aop:config、tx:advice
Spring AOP Schema aop:config.tx:advice 一. 利用aop:config标签实现AOP 首先看个例子,如下 接口代码: package com.lei. ...
- sql优化之(DMV)
原文地址:http://technet.microsoft.com/zh-cn/library/bb838723.aspx Microsoft SQL Server 2005 提供了一些工具来监控数据 ...
- HTML5+javascript实现图片加载进度动画效果
在网上找资料的时候,看到网上有图片加载进度的效果,手痒就自己也写了一个. 图片加载完后,隐藏loading效果. 想看加载效果,请ctrel+F5强制刷新或者清理缓存. 效果预览: 0% // ...
- iOS 企业证书发布app 流程
企业发布app的 过程比app store 发布的简单多了,没那么多的要求,哈 但是整个工程的要求还是一样,比如各种像素的icon啊 命名规范啊等等. 下面是具体的流程 1.修改你的 bundle i ...
- 在unity5中减少Draw Calls(SetPass Calls)[转]
在unity5中减少Draw Calls(SetPass Calls) 我一直工作于unity5支持的Standard Shader(标准着色器)上,并且做了一些关于如何有效地减少draw cal ...