Javascript面向对象的程序设计 —— 创建自定义类型的7种方法
Object构造函数或对象字面量都可以用来创建单个对象,但是使用这些方式用同一个接口创建很多对象,会产生大量的重复代码。为了解决这个问题,工厂模式的一种变体开始被使用。
1、工厂模式
工厂模式抽象了创建具体对象的过程。因为ECMAScript无法创建类,开发人员发明了一种函数,用函数来封装以特定接口创建对象的细节,如:
- 1 function createPerson(name, age, job){
- 2 var o = new Object();
- 3 o.name = name;
- 4 o.age = age;
- 5 o.job = job;
- 6 o.sayName = function(){
- 7 alert(this.name);
- 8 }
- 9 return o;
- 10 }
- 11 var person1 = createPerson("Anna", 26, "Software Engineer");
- 12 var person2 = createPerson("Lily", 24, "Teacher");
可以无数次调用createPerson()函数,它每次都会返回一个包含三个属性一个方法的对象。
工厂模式虽然可以创建多个对象,但无法识别对象的类型。
2、构造函数模式
构造函数可创建特定类型的对象,包括原生构造函数(如Object、Array)和自定义构造函数。
自定义构造函数,定义自定义对象类型的属性和方法,如:
- 1 function Person(name, age, job){ //惯例,构造函数以大写字母开头,非构造函数以小写字母开头
- 2 this.name = name; //构造函数直接将属性和方法赋给了this对象
- 3 this.age = age;
- 4 this.job = job;
- 5 this.sayName = function(){
- 6 alert(this.name);
- 7 };
- 8 }
- 9 //使用new操作符创建Person的新实例
- 10 var person1 = new Person("Anna", 26, "Software Engineer");
- 11 var person2 = new Person("Lily", 24, "Teacher");
使用new操作符调用构造函数会经理以下4个步骤:
(1)创建一个对象;
(2)将构造函数的作用域赋值给新对象(因此this就指向了这个新对象);
(3)执行构造函数中的代码(为这个新对象添加属性)。
(4)返回新对象。
创建的实例对象有一个constructor(构造函数)属性,该属性指向Person,如:
alert(person1.constructor == Person); //true
对象的constructor属性最初用来标识对象类型。但是检测对象类型,instanceof更可靠。例子中创建的对象既是Object的实例,也是Person的实例。如:
alert(person1 instanceof Object); //true 所有的对象均继承自Object
alert(person1 instanceof Person); //true
构造函数模式优于工厂模式的地方:自定义的构造函数的实例将来可以标识为一种特定的类型。
构造函数缺点:每个方法都要在每个实例上重新创建一遍。但是,创建多个完成同样任务的Function实例没有必要。
3、原型模式
创建的每一个函数都有一个prototype(原型)属性,是一个指针,指向一个对象,这个 对象包含可以由特定类型的所有实例共享的属性和方法。
使用原型的对象的好处:可以让所有对象实例共享它所包含的属性和方法。
- 1 function Person(){
- 2 }
- 3 Person.prototype.name = "Anna";
- 4 Person.prototype.age = 29;
- 5 Person.prototype.job = "Doctor";
- 6 Person.prototype.sayName = function(){
- 7 alert(this.name);
- 8 };
- 9 var person1 = new Person();
- 10 person1.sayName(); // "Anna"
- 11 var person2 = new Person();
- 12 person2.sayName(); // "Anna"
- 13 alert(person1.sayName == person2.sayName); //true
4、组合使用构造函数模式和原型模式
使用最广泛、认同度最高的一种建立自定义类型的方法,定义引用类型的默认模式。
构造函数模式用来定义实例属性,原型模式用来定义方法和共享的属性。
每个实例都会有自己的一份实例属性的副本,但同时共享着对方的引用,最大限度地节省了内存。
支持向构造函数传递参数。
- 1 function Person(name, age, job){
- 2 this.name = name;
- 3 this.age = age;
- 4 this.job = job;
- 5 this.friends = ["Shelby", "Court"];
- 6 }
- 7 Person.prototype = {
- 8 constructor: Person,
- 9 sayName: function(){
- 10 alert(this.name);
- 11 }
- 12 }
- 13 var person1 = new Person("Anna", 26, "Software Engineer");
- 14 var person2 = new Person("Greg", 27, "Doctor");
- 15
- 16 person1.friends.push("Van");
- 17 alert(person1.friends); // "Shelby,Court,Van"
- 18 alert(person2.friends); // "Shelby,Court"
- 19 alert(person1.friends === person2.friends); // false
- 20 alert(person1.sayName === person2.sayName); // true
5、动态原型模式
把所有信息都封装在了构造函数中,通过在构造函数中初始化原型(仅在必要的情况下),保持了同时使用构造函数和原型的优点。
- 1 function Person(name, age, job){
- 2 // 属性
- 3 this.name = name;
- 4 this.age = age;
- 5 this.job = job;
- 6 // 方法
- 7 if(typeof this.sayName != "function"){ //可以检查任何属性或方法之一即可
- 8 Person.prototype.syaName = function(){
- 9 alert(this.name);
- 10 };
- 11 }
- 12 }
- 13 var friend = new Person("Anna", 27, "Software Engineer");
- 14 friend.sayName();
这里对原型所做的修改,能够立即在所有实例中得到反映。
注:动态原型模式,不能使用对象字面量重写原型。如果已经创建实例后重写原型,会切断现有实例与新原型之间的联系。
6、寄生构造函数模式
创建一个函数,封装创建对象的代码,返回新创建的对象。
- 1 function Person(name, age, job){
- 2 var o = new Object();
- 3 o.name = name;
- 4 o.age = age;
- 5 o.job = job;
- 6 o.sayName = function(){
- 7 alert(this.name);
- 8 };
- 9 return o; //构造函数不返回值时,默认返回新对象实例;return返回值时,可以重写调用构造函数时返回的值
- 10 }
- 11 var friend = new Person("Anna", 27, "Software Engineer");
- 12 friend.sayName(); // "Anna"
假设创建一个有额外方法的特殊数组,由于不能直接修改Array构造函数,因此可以使用这个模式:
- 1 function SpecialArray(){
- 2 //创建数组
- 3 var values = new Array();
- 4 //添加值
- 5 values.push.apply(values, arguments);
- 6 //添加方法
- 7 values.toPipedString = function(){
- 8 return this.join("|");
- 9 };
- 10 //返回数组
- 11 return values;
- 12 }
- 13 var colors = new SpecialArray("red", "blue", "green");
- 14 alert(colors.toPipedString()); // "red|blue|green"
返回的对象与构造函数的原型属性之间没有关系,即构造函数返回的对象与在构造函数外部创建的对象没有什么不同。
不能依赖instanceof操作符来确定对象类型。建议在可以使用其他模式的情况下,不要使用这种模式。
7、稳妥构造函数模式
稳妥对象:没有公共属性,其方法也不引用this的对象。稳妥对象最适合在一些安全的环境中(这些环境禁止使用this和new),或者在防止数据被其他应用程序改动时使用。
- 1 function Person(name, age, job){
- 2 //创建要返回的对象
- 3 var o = new Object();
- 4 //可以在这里定义私有变量和属性
- 5
- 6 //添加方法
- 7 o.sayName = function(){
- 8 alert(name);
- 9 };
- 10 //返回对象
- 11 return o;
- 12 }
- 13 var friend =Person("Anna", 27, "Software Engineer");
- 14 friend.sayName(); // "Anna" 除了调用sayName()方法外,没有别的方式可以访问其数据成员
- 15 // 非常适合某些安全执行环境
注:使用稳妥构造函数模式创建的对象与构造函数之间也没有什么关系,因此instanceof操作符对这种对象也没有意义。
Javascript面向对象的程序设计 —— 创建自定义类型的7种方法的更多相关文章
- AutoCAD.NET二次开发:创建自定义菜单的两种方法比较
目前我已经掌握的创建CAD菜单方法有两种: COM方式: http://www.cnblogs.com/bomb12138/p/3607929.html CUI方式: http://www.cnblo ...
- 重学js之JavaScript 面向对象的程序设计(创建对象)
注意: 本文章为 <重学js之JavaScript高级程序设计>系列第五章[JavaScript引用类型]. 关于<重学js之JavaScript高级程序设计>是重新回顾js基 ...
- JavaScript 面向对象的程序设计
面向对象(Object-oriented,OO)的语言有一个标志,那就是它们都有类的概念.而通过类可以创建任意多个具有相同属性和方法的对象.前面提到过,ECMAScript中没有类的概念,因此它的对象 ...
- JavaScript 面向对象的程序设计(一)之理解对象属性
首先,JavaScript 面向对象的程序设计,主要分三部分. 理解对象属性: 理解并创建对象: 理解继承. 本文主要从第一方面来阐述: 理解对象属性 首先我们来理解Javascript对象是什么?在 ...
- JavaScript面向对象的程序设计
ECMAScript支持面对对象(oo)编程,但不使用类或接口.对象可以在代码执行过程中创建和增强,因此具有动态性而非严格定义的实体.在没有类的情况下,可以此采用下列模式创建对象. 工厂模式,使用简单 ...
- JavaScript面向对象—对象的创建和操作
JavaScript面向对象-对象的创建和操作 前言 虽然说在JavaScript编程语言中,函数是第一公民,但是JavaScript不仅支持函数式编程,也支持面向对象编程.JavaScript对象设 ...
- 面向对象的程序设计之JS创建对象的9种模式及其优缺点
目录 1.new Object () 2.字面式创建对象 3.工厂模式 4.构造函数模式 4.1.将构造函数当作函数 4.2.构造函数的问题 5.原型模式 5.1.理解原型对象 5.2.原型与in操作 ...
- Java 8创建Stream流的5种方法
不知不觉间,Java已经发展到13了,来不及感慨时间过得真的太快了,来不及学习日新月异的技术更新,目前大多数公司还是使用的JDK8版本,一方面是版本的稳定,另一方面是熟悉,所以很多公司都觉得不升级也挺 ...
- .net中创建xml文件的两种方法
.net中创建xml文件的两种方法 方法1:根据xml结构一步一步构建xml文档,保存文件(动态方式) 方法2:直接加载xml结构,保存文件(固定方式) 方法1:动态创建xml文档 根据传递的值,构建 ...
- Python中模拟enum枚举类型的5种方法分享
这篇文章主要介绍了Python中模拟enum枚举类型的5种方法分享,本文直接给出实现代码,需要的朋友可以参考下 以下几种方法来模拟enum:(感觉方法一简单实用) 复制代码代码如下: # way1 ...
随机推荐
- ps--提升字体排版的美感四个有效方法
一,文字的摆放位置 (字体的选择不要超过三种,分散注意力)
- WASI support in Go
原文在这里. 由 Johan Brandhorst-Satzkorn, Julien Fabre, Damian Gryski, Evan Phoenix, and Achille Roussel 发 ...
- Mysql数据库、表设计规范指南
结合网上资料与项目实际情况,总结下列MYSQL数据库设计规范. 一.MYSQL数据库设计规范1.数据库命名规范采用26个英文字母(区分大小写)和0-9的自然数(经常不需要)加上下划线'_'组成,禁止使 ...
- 【PHP反序列化】速览
PHP反序列化 一.原理 序列化就是将对象转化成字符串,反序列化相反.数据的格式转换和对象的序列化有利于对象的保存 . 反序列化漏洞:就是php对数据进行反序列化时,没有进行过滤,导致用户可以控制反序 ...
- Go 函数多返回值错误处理与error 类型介绍
Go 函数多返回值错误处理与error 类型介绍 目录 Go 函数多返回值错误处理与error 类型介绍 一.error 类型与错误值构造 1.1 Error 接口介绍 1.2 构造错误值的方法 1. ...
- 如何去掉桌面快捷方式左下角的小箭头(Win11)
在对系统重命名之后,在快捷方式的左下角莫名的出现了小图标 如果想要去掉这个小图标 (1)首先在桌面上创建一个txt文件 (2)打开后输入指令 reg add "HKEY_LOCAL_MACH ...
- CF1789D Serval and Shift-Shift-Shift 题解
题目链接 题目分析 首先,看到题目中的左移右移之后再异或,我们自然可以想到在移动的过程中字符串的一段前缀和后缀不会改变,考虑通过这个性质逐位还原. 因为异或 0 不会改变原本的值,所以我们可以找到整个 ...
- 一文读懂强化学习:RL全面解析与Pytorch实战
在本篇文章中,我们全面而深入地探讨了强化学习(Reinforcement Learning)的基础概念.主流算法和实战步骤.从马尔可夫决策过程(MDP)到高级算法如PPO,文章旨在为读者提供一套全面的 ...
- Electron-Vue中引入vue-devtools
效果图 先看下我引入后的效果图: 可以看到,跟在Chrome浏览器一样,会在开发者工具中出现一个Vue的标签,使用方式没有差别. 引入步骤 步骤一:下载安装vue-devtools 到vue-devt ...
- 算法训练 字符串的展开(isdigit与islower的发现)
在初赛普及组的"阅读程序写结果"的问题中,我们曾给出一个字符串展开的例子:如果在输入的字符串中,含有类似于"d-h"或者"4-8"的字串,我 ...