Javascript将构造函数扩展为简单工厂
一般而言,在Javascript中创建对象时需要使用关键字new(按构造函数去调用),但是某些时候,开发者希望无论new关键字有没有被显式使用,构造函数都可以被正常调用,即构造函数同时还具备简单工厂的职能。Javascript的一个特性使得这种『简单工厂式的构造函数』变得可行:如果构造函数中返回了对象,无论有没有使用new关键字,最终返回的值都是函数return的值。
基于这点特性,本文介绍了四种实现方式,抛砖引玉,欢迎拍砖~
1. 在构造函数中返回对象字面量
function Person(name) {
return {
name: name,
getName: function () {
return this.name;
}
};
}
console.log(new Person('Ralph').getName()); //Ralph
console.log(Person('Ralph').getName()); //Ralph
缺点:
不方便控制prototype属性,不利于高效扩展对象方法,instanceof操作符失效且constructor属性丢失
2. 在构造函数中使用内部函数构造对象
function Person(name) {
// lazy loading,在Person函数第一次被调用时初始化内部函数_Person
if (!Person.inited) {
Person._Person = function (name) {
this.name = name;
};
// 可以利用prototype进行方法扩展
Person._Person.prototype = {
// 正常使用constructor属性
constructor: Person,
getName: function () {
return this.name;
}
};
// 可以正常使用instanceof操作符
Person.prototype = Person._Person.prototype;
// 标记为已初始化
Person.inited = true;
}
return new Person._Person(name);
}
console.log(new Person('Ralph').getName()); //Ralph
console.log(Person('Ralph').getName()); //Ralph
缺点:
编码相对较为复杂,需要_Person作为辅助的内部构造函数,且需要手动修改prototype和constructor等属性
3. 利用instanceof操作符
function Person(name) {
// 如果使用了new,this指向新生成的Person实例
// 如果直接调用Person没有使用new,这里的this指向window对象
if (!(this instanceof Person)) {
return new Person(name);
}
this.name = name;
}
Person.prototype.getName = function () {
return this.name;
};
console.log(new Person('Ralph').getName()); //Ralph
console.log(Person('Ralph').getName()); //Ralph
缺点:
在判断this instanceof Person时需要指明构造函数名称Person,抽象程度不够高,修改构造函数名称时需要手动修改该语句
4. 利用callee属性和constructor属性
function Person(name) {
// arguments.callee指向Person函数
// this.constructor仅在使用了new的情形下指向Person函数
if (arguments.callee !== this.constructor) {
return new arguments.callee(name);
}
this.name = name;
}
Person.prototype.getName = function () {
return this.name;
};
console.log(new Person('Ralph').getName()); //Ralph
console.log(Person('Ralph').getName()); //Ralph
缺点:
strict模式下无法使用callee属性
(全文完)
Javascript将构造函数扩展为简单工厂的更多相关文章
- JavaScript设计模式--简单工厂模式
一,介绍 工厂模式创建对象(视为工厂里的产品)时无需指定创建对象的具体类. 工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类.该模式使一个类的实例化延迟到了子类.而子类可以重写接口 ...
- Javascript设计模式理论与实战:简单工厂模式
通常我们创建对象最常规的方法就是使用new关键字调用构造函数,这会导致对象之间的依赖性.工厂模式是一种有助于消除类之间依赖性的设计模式,它使用一个方法来决定要实例化哪一个类.本文详细介绍了简单工厂模式 ...
- 使用javascript完成一个简单工厂设计模式。
在JS中创建对象会习惯的使用new关键字和类构造函数(也是可以用对象字面量). 工厂模式就是一种有助于消除两个类依赖性的模式. 工厂模式分为简单工厂模式和复杂工厂模式,这篇主要讲简单工厂模式. 简单工 ...
- 再起航,我的学习笔记之JavaScript设计模式05(简单工厂模式)
我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前几 ...
- C#中的简单工厂和单例
下面首先来说说简单工厂 举个例子: 首先是父类 public abstract class Pizza { public abstract string Info(); } } 子类 public c ...
- Design Patterns (简单工厂模式)
文章很长很精彩,如是初学请耐心观看.(大神请绕道!) 简单工厂模式: 1.创建型模式 2.简单工厂模式概述 3.简单工厂模式的结构与实现 4.简单工厂模式的应用实例 5.创建对象与使用对象 6.简单工 ...
- 设计模式的征途—2.简单工厂(Simple Factory)模式
工厂模式是最常用的一种创建型模式,通常所说的工厂模式一般是指工厂方法模式.本篇是是工厂方法模式的“小弟”,我们可以将其理解为工厂方法模式的预备知识,它不属于GoF 23种设计模式,但在软件开发中却也应 ...
- 用C#(.NET Core) 实现简单工厂和工厂方法模式
本文源自深入浅出设计模式. 只不过我是使用C#/.NET Core实现的例子. 前言 当你看见new这个关键字的时候, 就应该想到它是具体的实现. 这就是一个具体的类, 为了更灵活, 我们应该使用的是 ...
- java之设计模式工厂三兄弟之简单工厂模式
[学习难度:★★☆☆☆,使用频率:★★★☆☆] 工厂模式是最常用的一类创建型设计模式,通常我们所说的工厂模式是指工厂方法模式,它也是使用频率最高的工厂模式.本章将要学习的简单工厂模式是工厂方法模式的& ...
随机推荐
- CSS之旅——第三站 强大的伪选择器
说到伪选择器,真的让我体会到了CSS的无比强大,强大到自己貌似都不认识CSS了,有点C# 6.0中一些语法糖带给我们的震撼...首先 我们可以在VS里面提前预览一下. 可以看到,上面的伪类有很多很多, ...
- NOSQL(一)--Redis
简介 最近开始接触NoSQL,翻译过来就是 not only sql,非关系型数据库吧. 其中主要有四大类NoSQL,今天我们介绍其中的一种键值对的NoSQL:Redis. 定义:Redis是一个开源 ...
- php配置php-fpm启动参数及配置详解
约定几个目录 /usr/local/php/sbin/php-fpm/usr/local/php/etc/php-fpm.conf/usr/local/php/etc/php.ini一,php-fpm ...
- SQL Server 2000 sp2 及更低版本不受此版本的 Windows 支持
SQL Server 2000 sp2 及更低版本不受此版本的 Windows 支持.在安装了 SQL Server 2000 之后请应用 sp3. 出现这种现象的原因在于:Windows Serve ...
- Visual Studio 2012中文旗舰版(序列号和下载地址)
序列号:YKCW6-BPFPF-BT8C9-7DCTH-QXGWC 链接: http://pan.baidu.com/s/1pLGhDjl 密码: 3udq
- android MotionEvent 获取长按压时间长
思路: 1.记录ACTION_DOWN的aX, aY坐标: 2.在ACTION_MOVE判断是否移动,移动则取消记录时间,没移动就记录: 3.记录时间,按下坐标,移动坐标分别显示在TextView a ...
- java 读取文件——按照行取出(使用BufferedReader和一次将数据保存到内存两种实现方式)
1.实现目标 读取文件,将文件中的数据一行行的取出. 2.代码实现 1).方式1: 通过BufferedReader的readLine()方法. /** * 功能:Java读取txt文件的内容 步骤: ...
- uva 6757 Cup of Cowards(中途相遇法,貌似)
uva 6757 Cup of CowardsCup of Cowards (CoC) is a role playing game that has 5 different characters (M ...
- Linux命令整理中...
Linux命令整理中... 最常用命令(我最近最常用的一般放在前面tipsbychsry) clear 清屏 date 显示日期 cal 显示日历 cal 2014 显示2014年的日历 shutdo ...
- bg激活后台运行的服务
按redis重启来做案例 ./redis-server Ctrl+z让执行的命令在后台暂停 [1]+ Stopped ./redis-server 这个时候他是把这个服务放到后台了,可是ctrl+z是 ...