设计模式之构造函数模式
介绍
构造函数大家都很熟悉了,不过如果你是新手,还是有必要来了解一下什么叫构造函数的。构造函数用于创建特定类型的对象——不仅声明了使用的对象,构造函数还可以接受参数以便第一次创建对象的时候设置对象的成员值。你可以自定义自己的构造函数,然后在里面声明自定义类型对象的属性或方法。
基本用法
在JavaScript里,构造函数通常是认为用来实现实例的,JavaScript没有类的概念,但是有特殊的构造函数。通过new关键字来调用定义的否早函数,你可以告诉JavaScript你要创建一个新对象并且新对象的成员声明都是构造函数里定义的。在构造函数内部,this关键字引用的是新创建的对象。基本用法如下:
function Car(model, year, miles) { this.model = model; this.year = year; this.miles = miles; this.output= function () { return this.model + "走了" + this.miles + "公里"; };} var tom= new Car("大叔", 2009, 20000);var dudu= new Car("Dudu", 2010, 5000); console.log(tom.output());console.log(dudu.output());
上面的例子是个非常简单的构造函数模式,但是有点小问题。首先是使用继承很麻烦了,其次output()在每次创建对象的时候都重新定义了,最好的方法是让所有Car类型的实例都共享这个output()方法,这样如果有大批量的实例的话,就会节约很多内存。
解决这个问题,我们可以使用如下方式:
function Car(model, year, miles) { this.model = model; this.year = year; this.miles = miles; this.output= formatCar;} function formatCar() { return this.model + "走了" + this.miles + "公里";}
这个方式虽然可用,但是我们有如下更好的方式。
构造函数与原型
JavaScript里函数有个原型属性叫prototype,当调用构造函数创建对象的时候,所有该构造函数原型的属性在新创建对象上都可用。按照这样,多个Car对象实例可以共享同一个原型,我们再扩展一下上例的代码:
function Car(model, year, miles) { this.model = model; this.year = year; this.miles = miles;} /*注意:这里我们使用了Object.prototype.方法名,而不是Object.prototype主要是用来避免重写定义原型prototype对象*/Car.prototype.output= function () { return this.model + "走了" + this.miles + "公里";}; var tom = new Car("大叔", 2009, 20000);var dudu = new Car("Dudu", 2010, 5000); console.log(tom.output());console.log(dudu.output());
这里,output()单实例可以在所有Car对象实例里共享使用。
另外:我们推荐构造函数以大写字母开头,以便区分普通的函数。
只能用new吗?
上面的例子对函数car都是用new来创建对象的,只有这一种方式么?其实还有别的方式,我们列举两种:
function Car(model, year, miles) { this.model = model; this.year = year; this.miles = miles; // 自定义一个output输出内容 this.output = function () { return this.model + "走了" + this.miles + "公里"; }} //方法1:作为函数调用Car("大叔", 2009, 20000); //添加到window对象上console.log(window.output()); //方法2:在另外一个对象的作用域内调用var o = new Object();Car.call(o, "Dudu", 2010, 5000);console.log(o.output());
该代码的方法1有点特殊,如果不适用new直接调用函数的话,this指向的是全局对象window,我们来验证一下:
//作为函数调用var tom = Car("大叔", 2009, 20000);console.log(typeof tom); // "undefined"console.log(window.output()); // "大叔走了20000公里"
这时候对象tom是undefined,而window.output()会正确输出结果,而如果使用new关键字则没有这个问题,验证如下:
//使用new 关键字var tom = new Car("大叔", 2009, 20000);console.log(typeof tom); // "object"console.log(tom.output()); // "大叔走了20000公里"
强制使用new
上述的例子展示了不使用new的问题,那么我们有没有办法让构造函数强制使用new关键字呢,答案是肯定的,上代码:
function Car(model, year, miles) { if (!(this instanceof Car)) { return new Car(model, year, miles); } this.model = model; this.year = year; this.miles = miles; this.output = function () { return this.model + "走了" + this.miles + "公里"; }} var tom = new Car("大叔", 2009, 20000);var dudu = Car("Dudu", 2010, 5000); console.log(typeof tom); // "object"console.log(tom.output()); // "大叔走了20000公里"console.log(typeof dudu); // "object"console.log(dudu.output()); // "Dudu走了5000公里"
通过判断this的instanceof是不是Car来决定返回new Car还是继续执行代码,如果使用的是new关键字,则(this instanceof Car)为真,会继续执行下面的参数赋值,如果没有用new,(this instanceof Car)就为假,就会重新new一个实例返回。
原始包装函数
JavaScript里有3中原始包装函数:number, string, boolean,有时候两种都用:
// 使用原始包装函数var s = new String("my string");var n = new Number(101);var b = new Boolean(true); // 推荐这种var s = "my string";var n = 101;var b = true;
推荐,只有在想保留数值状态的时候使用这些包装函数,关于区别可以参考下面的代码:
// 原始stringvar greet = "Hello there";// 使用split()方法分割greet.split(' ')[0]; // "Hello"// 给原始类型添加新属性不会报错greet.smile = true;// 单没法获取这个值(18章ECMAScript实现里我们讲了为什么)console.log(typeof greet.smile); // "undefined" // 原始stringvar greet = new String("Hello there");// 使用split()方法分割greet.split(' ')[0]; // "Hello"// 给包装函数类型添加新属性不会报错greet.smile = true;// 可以正常访问新属性console.log(typeof greet.smile); // "boolean"
总结
本章主要讲解了构造函数模式的使用方法、调用方法以及new关键字的区别,希望大家在使用的时候有所注意。
2017-08-28 12:57:57
转载于:https://www.cnblogs.com/guangzhou11/articles/7443331.html
设计模式之构造函数模式相关推荐
- JavaScript 设计模式之构造函数模式
一.构造函数模式概念解读 1.构造函数模式概念文字解读 构造函数用于创建特定类型的对象--不仅声明了使用的对象,构造函数还可以接受参数以便第一次创建对象的时候设置对象的成员值.你可以自定义自己的构造函 ...
- javascript --- 设计模式之构造函数模式
在JavaScript里,构造函数通常是认为用来实现实例的,JavaScript没有类的概念,但是有特殊的构造函数.通过new关键字来调用定义的否早函数,你可以告诉JavaScript你要创建一个新对 ...
- js设计模式每次10分钟:字面量和构造函数模式对比
字面量和构造函数模式 字面量 var dog={} dog.name="benji"; //属性 dog.getName=function(){ //方法return this.n ...
- Java设计模式之策略模式与状态模式
一.策略模式定义 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们之间可以相互替换,策略模式可以在不影响客户端的情况下发生变化. 好了,定义看看就完了,我知道你很烦看定义. 二.策 ...
- 【设计模式】策略模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
文章目录 一.策略模式简介 二.策略模式适用场景 三.策略模式优缺点 四.策略模式与其它设计模式 五.策略模式代码示例 1.促销策略接口 2.满减促销策略 3.返现促销策略 4.空促销策略 5.促销策 ...
- 设计模式-行为型模式-中介者模式
设计模式-行为型模式-中介者模式 行为型模式 划分类和对象的职责. 中介者模式 进销存管理,即采购,销售,库存. 其中类图 代码如下 public class Purchase {// 采购IBM电脑 ...
- 乐在其中设计模式(C#) - 提供者模式(Provider Pattern)
原文:乐在其中设计模式(C#) - 提供者模式(Provider Pattern) [索引页] [源码下载] 乐在其中设计模式(C#) - 提供者模式(Provider Pattern) 作者:web ...
- JavaScript --- [学习笔记]观察者模式 理解对象 工厂模式 构造函数模式
说明 本系列(JS基础梳理)为后面TCP的模拟实现做准备 本篇的主要内容: 观察者模式.工厂模式.构造函数模式 和 对对象的理解 1. 观察者模式 参考JavaScript设计模式 1.1 消息注册方 ...
- 设计模式装饰者模式_装饰者模式如何拯救了我的一天
设计模式装饰者模式 在工作中,我正在处理庞大的Java代码库,该代码库是由许多不同的开发人员在15年的时间里开发的. 并不是所有的事情都由书来完成,但是同时我通常无法重构遇到的每一个奇怪的事物. 尽管 ...
- Android设计模式之——Builder模式
一.介绍 Builder模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细的控制对象的构造流程.该模式是为了将构建复杂对象的过程和它的部件解耦,使得构建过程 ...
最新文章
- python常用的基本操作
- 149. Leetcode 1005. K 次取反后最大化的数组和 (贪心算法-基础题目)
- Condition总结-await和signal的总结
- AttributeError: 'dict' object has no attribute 'iteritems' python3报错
- ichartjs android,在android上动态实现ichartjs的3D柱形图
- 如何查找数据库服务器ip_多服务器管理–查找数据库服务器
- datatable插件实现分页功能
- ES测试数据,kibana命令
- 冲刺计划sprint
- VMware vRealize Suite 8.8.0
- 求区域的最大内接矩形
- iphone个系列尺寸_iPhone9只是套模iPhone8,这些才是iPhone经典款,你用过哪些?
- 好消息!iPhone 4, 3GS, 3G 基带 5.14.02 和 2.10.4 已经软解
- 盘点百位富豪读过的大学:土鳖比海龟更有优势
- [别被脱裤系列]2 还没深入数据库就浅出了
- 工商银行u盾 java_中国工商银行u盾怎么用
- 成都物韵电子商务有限公司拼多多代运营若干技巧
- 全文检索技术Lucene入门和学习、与数据库数据结合的demo实现
- 如何快速的清除 灰鸽子 木马病毒 【附清除工具 以及 清除原理】
- weblogic12C如何解决AdminServer.lok问题