JavaScript中创建自定义对象的方法
本文内容参考JavaScript高级程序设计(第3版)第6章:面向对象的程序设计
ECMA-262中把对象定义为:“无序属性的集合,其属性可以包含基本值、对象或者函数。”我所理解的就是对象就是一个结构体,结构体中有一些它的基本属性以及对结构体处理的方法,把它们封装起来称为一个整体。JS中所有的对象都是基于一个引用类型创建,这个引用类型可以是原生类型,如Array,Date等,也可以是开发人员自定义的类型。
下面主要总结下JS中创建对象的几种模式,分析他们各自的优缺点。
1. 工厂模式
/******************工厂模式*************************/
/***使用同一个接口创建多个对象,避免代码重复,用一个函数来封装以特定接口创建对象的细节***/
/*****缺点:不能识别对象的类型(都是Object类型)******/
function createPerson(name, age, job)
{
var object = new Object();
object.name = name;
object.age = age;
object.job = job;
object.sayName = function()
{
alert(this.name);
}
return object;
} var person1 = createPerson("Jack", "22", "singer");
var person2 = createPerson("Taylor", "30", "actor");
工厂模式创建一个接口函数,在接口函数中新建一个对象,并为其定义属性和方法,每创建一个新的对象就调用这个接口函数。这种模式避免了创建同一类型对象的代码重复,但是这样创建的对象都是Object类型,无法体现出自定义类型的独特性。
2.构造函数模式
/******************构造函数模式***********************/
/****与工厂模式的区别:********************************/
/****1.没有显式地创建对象******************************/
/****2.直接将属性和方法赋给了this对象*******************/
/****3.没有return语句*******************************/
/****缺点:每实例化一个对象就新创建了一个不同的Function实例(对象中的方法函数)*/
function Person(name, age, job)
{
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() //每实例化一个对象就新创建一个Function实例
{
alert(this.name);
}
} var person1 = new Person("Jack", "22", "singer");
var person2 = new Person("Taylor", "30", "actor"); //Person为实例的特定类型
构造函数模式也创建了一个函数接口,不过与工厂模式不同的是这不是普通的函数,而是构造函数。构造函数与普通函数在定义上没有区别,只是构造函数在调用时要在函数名前加一个“new”。用构造函数模式创建的对象有自己的类型名(如本例中的Person),但是它依然有缺陷:对象中的方法函数没有必要实例化,它最好可以只定义一次让所有同类型的对象共用,在这种模式下,每新建一个对象就新建了一次对象中的方法函数,代码不够简洁。
3.原型模式
/**********************原型模式************************/
/****原型对象可以让所有对象实例共享它所包含的属性和方法********/
/****缺点:所有实例在默认情况下都将取得相同的属性值,没有属于自己的属性值*****/
function Person()
{}
Person.prototype.name = "Louis";
Person.prototype.age = "23";
Person.prototype.job = "singer";
Person.prototype.friend = ["Harry", "Liam"];
Person.prototype.sayName = function()
{
alert(this.name);
}; var person1 = new Person();
var person2 = new Person(); person1.age = "28"; //屏蔽原型对象中age属性,但不修改原型中的属性
alert(person1.age); // 28 来自实例
alert(person2.age); // 23 来自原型 person1.friend.push("zyan"); //修改了person1.friend引用的数组--原型对象中的属性
alert(person1.friend); // "Harry,Liam,Zayn"
alert(person2.friend); // "Harry,Liam,Zayn"
alert(person1.friend == person2.friend) // true
无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个propotype属性,这个属性指向这个函数的原型对象。同时,这个原型对象也会获得一个constructor属性,这个属性包含一个指向这个新函数的指针。而调用构造函数创建一个新实例后,该实例的内部又将包含一个内部指针[[propotype]],这个指针指向构造函数的原型对象。原型对象中的属性和方法可以被所有对象的实例共享。
获取某个实例的属性时,先搜索实例本身,也就是它的构造函数里有没有这个属性,如果有就直接返回这个值,如果没有则继续搜索构造函数的原型对象中的属性。所以在某一个对象中添加一个原型中已有的属性或方法时,会屏蔽原型中的属性,但原型中的属性不会被修改。
共享是原型模式的优点,它避免了大量重复的代码,但同时也带来了弊端。如示例中,在原型对象中定义了一个引用类型Array的属性--friend,person1实例向数组中添加了一项,但由于friend属性也同时在person2中,所以person2中的friend也跟着改变了,这不利于各个实例的独特性。
4.组合使用构造函数模式和原型模式
/****************构造函数模式和原型模式混合********************/
/****构造函数模式用于定义实力属性,原型模式用于定义方法和共享属性****/
/****每个实例都有自己的一份实例属性副本,方法共享,节省内存*********/
function Person(name, age, job)
{
this.name = name;
this.age = age;
this.job = job;
this.friend = ["Harry", "Liam"];
}
Person.prototype.sayName = function()
{
alert(this.name);
} var person3 = new Person("Lious", 22, "singer");
var person4 = new Person("Zyan", 21, "dancer"); person3.friend.push("Nail");
alert(person3.friend); //"Harry,Liam,Nail"
alert(person4.friend); //"Harry,Liam"
这种方法综合了构造函数模式和原型模式的优点,构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性。每个实例都会有自己的一份实例属性的副本,同时又共享着对方法的引用,最大限度地节省了内存。在这种模式下person1改变它的friend属性并不会影响到person2,因为friend属性写在了构造函数中,每创建一个新的实例都会生成这个属性的新的副本,所以person1和person2中的friend数组是不同的数组。
构造函数模式个原型模式的混合模式是实际开发中最常用的创建对象的模式。
JavaScript中创建自定义对象的方法的更多相关文章
- Javascript 中创建自定义对象的方法(设计模式)
Javascript 中创建对象,可以有很多种方法. Object构造函数/对象字面量: 抛开设计模式不谈,使用最基本的方法,就是先调用Object构造函数创建一个对象,然后给对象添加属性. var ...
- JS中创建自定义对象的方法
1.直接给对象扩充属性和方法: 2.对象字面量: 3.工厂方式: 4.构造函数方式: 5.原型方式: 6.混合方式. <script> // 1.直接给对象扩充属性和方法; var cat ...
- JavaScript中创建字典对象(dictionary)实例
这篇文章主要介绍了JavaScript中创建字典对象(dictionary)实例,本文直接给出了实现的源码,并给出了使用示例,需要的朋友可以参考下 对于JavaScript来说,其自身的Array对象 ...
- 简单使用JSON,JavaScript中创建 JSON 对象(一)
JSON:JavaScript 对象表示法(JavaScript Object Notation). JSON 是存储和交换文本信息的语法.类似 XML. JSON 比 XML 更小.更快,更易解析. ...
- JavaScript 中有关数组对象的方法
JS 处理数组多种方法 js 中的数据类型分为两大类:原始类型和对象类型. 原始类型包括:数值.字符串.布尔值.null.undefined 对象类型包括:对象即是属性的集合,当然这里又两个特殊的对象 ...
- 在JavaScript中重写jQuery对象的方法
jQuery是一个很好的类库,它给我们解决了很多的客户端编程,任何东西都不是万能的,当它不能满足我们的需求时我们需要对它进行重写,同时也不要影响其原有的功能或者修改其原有的功能:我现在的web应用程序 ...
- Floodlight 中创建消息对象的方法
在 floodlight 中创建各种openflow message 和 action 等採用的是简单工厂方式.BasicFactory类(实现OFMessageFactory接口.) ...
- java4中创建内对象的方法
在java程序中,对象可以被显式地或者隐式地创建.四种显式的创建对象的方式: ● 用new语句创建对象 ● 运用反射手段,调用java.lang.Class 或者 java.lang. ...
- JavaScript中的string对象及方法
string对象 string对象的两种创建 var a="hello"; var b=new String("hello"); //下面是方法 //charA ...
随机推荐
- Vue.js:计算属性
ylbtech-Vue.js:计算属性 1.返回顶部 1. Vue.js 计算属性 计算属性关键词: computed. 计算属性在处理一些复杂逻辑时是很有用的. 可以看下以下反转字符串的例子: 实例 ...
- Centos7部署CephFS
标签(空格分隔): ceph环境,ceph,cephfs cephfs部署之前准备工作: 1. 一个 clean+active 的cluster cluster部署参考:centos7下搭建ceph ...
- 源码编译安装ceph
标签(空格分隔): ceph,ceph安装,ceph运维 centos7系统,aarch64架构下安装最新版本的ceph(13.0.0),x86架构的环境无需修改脚本即可. 一,物理环境: 内核版本: ...
- 第八章 JVM内存管理
8.1 物理内存与虚拟内存 地址总线(连接处理器和RAM或处理器和寄存器的)的宽度影响了物理地址的索引范围,决定了处理器一次可以从寄存器或内存中获取多少个bit.同时决定了处理器最大的寻址空间,32位 ...
- wordpress 学习笔记
(1) __()函数 function __( $text, $domain = 'default' ) { return translate( $text, $domain ); } 返回一个字符串 ...
- xcode找回欢迎界面
[xcode找回欢迎界面] 有一次嫌xcode界面烦,点击了以下checkbox取消了欢迎界面: 随后发现没了欢迎界面反而更不方便,一心想找回欢迎界面,Preference里找了半天没找到开关,原来开 ...
- SSM框架整合(Spring+SrpingMVC+Mybatis) 简单案例
简介: SSM框架是Spring,SpringMVC 和Mybatis框架的整合,是标准的MVC模式,将整个系统划分为表现层,controller层,service层,dao层四层. Spring实现 ...
- 【bzoj2947】[Poi2000]促销
2947: [Poi2000]促销 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 181 Solved: 120[Submit][Status][D ...
- Linux 下Nginx 运行Vue
首相基础的安装Node.js npm 先建个目录把 /node/www 然后在这个目录下 wget https://nodejs.org/dist/v8.11.1/node-v8.11.1-linu ...
- c++ deque 容器
deque (全名 double ended queue)是一种具有队列和栈一样的数据结构. 在c++标准库中几乎和vector容器的接口完全相同,但它和vector 还是有一些细微的差别. 1. d ...