Effective JavaScript Item 33 让构造函数不再依赖newkeyword
本系列作为EffectiveJavaScript的读书笔记。
在将function当做构造函数使用时,须要确保该函数是通过newkeyword进行调用的。
function User(name, passwordHash) {
this.name = name;
this.passwordHash = passwordHash;
}
假设在调用上述构造函数时。忘记了使用newkeyword。那么:
var u = User("baravelli", "d8b74df393528d51cd19980ae0aa028e");
u; // undefined
this.name; // "baravelli"
this.passwordHash; // "d8b74df393528d51cd19980ae0aa028e"
能够发现得到的u是undefined。而this.name以及this.passwordHash则被赋了值。可是这里的this指向的则是全局对象。
假设将构造函数声明为依赖于strict模式:
function User(name, passwordHash) {
"use strict";
this.name = name;
this.passwordHash = passwordHash;
}
var u = User("baravelli", "d8b74df393528d51cd19980ae0aa028e");
// error: this is undefined
那么在忘记使用newkeyword的时候,在调用this.name= name的时候会抛出TypeError错误。这是由于在strict模式下。this的默认指向会被设置为undefined而不是全局对象。
那么,是否有种方法可以保证在调用一个函数时,不管使用了newkeyword与否,该函数都可以被当做构造函数呢?以下的代码是一种实现方式。使用了instanceof操作:
function User(name, passwordHash) {
if (!(this instanceof User)) {
return new User(name, passwordHash);
}
this.name = name;
this.passwordHash = passwordHash;
} var x = User("baravelli", "d8b74df393528d51cd19980ae0aa028e");
var y = new User("baravelli", "d8b74df393528d51cd19980ae0aa028e");
x instanceof User; // true
y instanceof User; // true
以上的if代码块就是用来处理没有使用new进行调用的情况的。当没有使用new时。this的指向并非一个User的实例。而在使用了newkeyword时,this的指向是一个User类型的实例。
还有一个更加适合在ES5环境中使用的实现方式例如以下:
function User(name, passwordHash) {
var self = this instanceof User ? this : Object.create(User.prototype);
self.name = name;
self.passwordHash = passwordHash;
return self;
}
Object.create方法是ES5提供的方法。它可以接受一个对象作为新创建对象的prototype。
那么在非ES5环境中,就须要首先实现一个Object.create方法:
if (typeof Object.create === "undefined") {
Object.create = function(prototype) {
function C() { }
C.prototype = prototype;
return new C();
};
}
实际上,Object.create方法还有接受第二个參数的版本号,第二个參数表示的是在新创建对象上赋予的一系列属性。
当上述的函数确实使用了new进行调用时。也可以正确地得到返回的新建对象。这得益于构造器覆盖模式(Constructor Override Pattern)。该模式的含义是:使用了newkeyword的表达式的返回值可以被一个显式的return覆盖。
正如以上代码中使用了returnself来显式定义了返回值。
当然。以上的工作在某些情况下也不是必要的。可是,当一个函数是须要被当做构造函数进行调用时,必须对它进行说明,使用文档是一种方式。将函数的命名使用首字母大写的方式也是一种方式(基于JavaScript语言的一些约定俗成)。
总结:
- 使用Object.create来保证一个函数确实是被当做一个构造函数进行调用的,不管newkeyword是否被使用了。
- 对于作为构造函数的函数。在文档中指明这一点来保证其它用户可以正确的使用它。
Effective JavaScript Item 33 让构造函数不再依赖newkeyword的更多相关文章
- Effective JavaScript Item 38 调用父类的构造函数在子类的构造函数
作为这一系列Effective JavaScript的读书笔记. 在一个游戏或者图形模拟的应用中.都会有场景(Scene)这一概念.在一个场景中会包括一个对象集合,这些对象被称为角色(Actor). ...
- Effective JavaScript Item 40 避免继承标准类型
本系列作为Effective JavaScript的读书笔记. ECMAScript标准库不大.可是提供了一些重要的类型如Array,Function和Date.在一些场合下.你或许会考虑继承当中的某 ...
- Effective JavaScript Item 21 使用apply方法调用函数以传入可变參数列表
本系列作为Effective JavaScript的读书笔记. 以下是一个拥有可变參数列表的方法的典型样例: average(1, 2, 3); // 2 average(1); // 1 avera ...
- Effective JavaScript Item 46 优先使用数组而不是Object类型来表示有顺序的集合
本系列作为Effective JavaScript的读书笔记. ECMAScript标准并没有规定对JavaScript的Object类型中的属性的存储顺序. 可是在使用for..in循环对Objec ...
- Effective JavaScript Item 37 认识this的隐式指向
本系列作为Effective JavaScript的读书笔记. CSV数据通常都会被某种分隔符进行分隔.所以在实现CSV Reader时,须要支持不同的分隔符.那么,非常自然的一种实现就是将分隔符作为 ...
- Effective JavaScript Item 39 绝不要重用父类型中的属性名
本系列作为Effective JavaScript的读书笔记. 假设须要向Item 38中的Actor对象加入一个ID信息: function Actor(scene, x, y) { this.sc ...
- Effective JavaScript Item 30 理解prototype, getPrototypeOf和__proto__的不同
本系列作为Effective JavaScript的读书笔记. prototype,getPropertyOf和__proto__是三个用来訪问prototype的方法.它们的命名方式非常类似因此非常 ...
- Effective JavaScript Item 10 避免使用with
本系列作为Effective JavaScript的读书笔记. Item 9:避免使用withkeyword 重点: 设计withkeyword本来是为了让代码变简洁,可是却起到了相反的效果.比方: ...
- Effective JavaScript Item 31 优先使用Object.getPrototypeOf,而不是__proto__
本系列作为Effective JavaScript的读书笔记. 在ES5中引入了Object.getPrototypeOf作为获取对象原型对象的标准API.可是在非常多运行环境中.也提供了一个特殊的_ ...
随机推荐
- 使用Iperf工具测试android系统网络wifi的吞吐量wifithrougput
http://blog.csdn.net/bingxuebage/article/details/7534655 服务端:./iperf3 -s &客户端:./iperf3 -c 10.15. ...
- 图片预加载插件 preLoad.js
1.preLoad.js插件 /*! * preLoad.js v1.0 * (c) 2017 Meng Fangui * Released under the MIT License. */ (fu ...
- cydia源
http://apt.91.com http://apt.178.com Flex 2的官方安装源是 getdelta.co
- openerp修改logo和title
LOGO的修改addons\web\static\src\img下面的:favicon.ico文件和logo2.png \addons\web\static\src\xml\base.xml#82 l ...
- Flash builder 调试技巧 (分享)
如果这个Flash能直接自己运行,例如Air或者简单不依赖于外部网页的flash,当然非常容易调试.直接F11嘛~~~ 但是,如果这个Flash要依赖于外部环境才能运行,那该怎么调试呢? 核心 ...
- google打不开解决的方法
14.5.27以来.谷歌又打不开了. 从网上找了些国内的googleserverIP,例如以下: const char* g_google_ips[18] = { "203.208.48.1 ...
- JAVA中定义常量的几种方式
1.最古老的 //未处理 public static final Integer PROCESS_STATUS_UNTREATED = 0; //已接收 public static final Int ...
- 混合用法模式 __name__和__main__
# -*- coding: utf-8 -*- #python 27 #xiaodeng #混合用法模式 __name__和__main__ #可把文件作为模块导入,并以独立式程序的形式运行,每个模块 ...
- PHP 大数自动转换为科学计数法
前段时间碰到一个很头疼的问题,就是大于12位的数字在PHP中,会自动转成科学计数法表 示. 比如 1234567891234 显示为 1.23456789123E+12 , 最后只能在计算出大数之后, ...
- ZOJ 3203 Light Bulb (三分查找)
Light Bulb Time Limit: 1 Second Memory Limit: 32768 KB Compared to wildleopard's wealthiness, h ...