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之设计模式工厂三兄弟之简单工厂模式
[学习难度:★★☆☆☆,使用频率:★★★☆☆] 工厂模式是最常用的一类创建型设计模式,通常我们所说的工厂模式是指工厂方法模式,它也是使用频率最高的工厂模式.本章将要学习的简单工厂模式是工厂方法模式的& ...
随机推荐
- Sql Server之旅——第四站 你必须知道的非聚集索引扫描
非聚集索引,这个是大家都非常熟悉的一个东西,有时候我们由于业务原因,sql写的非常复杂,需要join很多张表,然后就泪流满面了...这时候就 有DBA或者资深的开发给你看这个猥琐的sql,通过执行计划 ...
- 【JSP】JSP基础学习记录(一)—— 基础介绍以及3个编译指令
序: 从实现到现在一直是以.net为主,但偶尔也会参与一些其他语言的项目.最近需要对一个Java Web项目进行二次开发,一直没学习过JSP所以买了几本书自学试试.参考资料为<轻量级Java E ...
- C# 读取在存储过程多结果集
--SQL Server 测试环境搭建: Create database Test; go USE [Test] GO if OBJECT_ID('Tab','U') is not null drop ...
- http状态码详细说明
100 客户端应当继续发送请求.这个临时响应是用来通知客户端它的部分请求已经被服务器接收,且仍未被拒绝.客户端应当继续发送请求的剩余部分,或者如果请求已经完成,忽略这个响应.服务器必须在请求完 ...
- Eclipse快捷键-方便查找
[Ct rl+T] 搜索当前接口的实现类 1. [ALT +/] 此快捷键为用户编辑的好帮手,能为用户提供内容的辅助,不要为记不全方法和属性名称犯愁,当记不全类.方法和属性的名字时,多体验一下[ ...
- Redis-benchmark测试Redis性能
Redis-benchmark是官方自带的Redis性能测试工具,可以有效的测试Redis服务的性能. 使用说明如下: Usage: redis-benchmark [-h <host>] ...
- Android Fragment初探:静态Fragment组成Activity
一直习惯了在Activity中写所有事件处理代码,直到认真学习Fragment时,才发现,Activity完全可以由多个Fragment组成. 对Fragment的了解还不够深入,先从静态Fragme ...
- php 连续留存与留存人数计算
for($i = 0;$i <= $interval;$i++) { $res = $model->turnround($today,$tomorrow,$flag); $temp = a ...
- 不就是抽个血吗,至于么-jQuery,Linux完结篇
hi 趁着周一去抽血化验,真开心...下午报告才出来,不过早上来了就开始各种晕菜,叫错名字,说错话.....至于么.. 还有在教研室的30天就可以肥家了,凯森凯森.今天不想干活(哪天想干过我就问问), ...
- Java实现点击一个控件实现删除一个控件的方法
最近在做项目的时候需要处理点击一个JLabel实现删除这一个JLabel的功能.最近折磨了一点时间,查了一下API.找到2个方法可以实现这个功能. remove public void remove( ...