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.可是在非常多运行环境中.也提供了一个特殊的_ ...
随机推荐
- iOS 获取流量
#include <arpa/inet.h> #include <net/if.h> #include <ifaddrs.h> #include <net/i ...
- [置顶] macbook 深度休眠和待机
开发用了macbook pro, 10.8.3, 因为用windows的习惯,一直比较习惯不关机,直接休眠,不是待机standby,今天找到了一个工具,可以实现,亲测通过. 下载:https://gi ...
- GraphQL返回分页对象
private GraphQLOutputType testUserOutputType; private GraphQLOutputType pageType; private void initO ...
- asp.net 使用JS获得串口数据
使用JS获得串口数据 JavaScript语言通常是一种网页编程语言,比较适合前台的一些应用设计.对于本地设备和数据的操作有比较大的限制.由于项目的需要,我需要获得本机的串口数据并显示在web端.我们 ...
- Linux虚拟机下使用USB转串口线——配置minicom、以及screen的使用
转自:http://bbs.ednchina.com/BLOG_ARTICLE_637212.HTM 环境:Windows XP + (VMware Workstation - Linux) 1.确保 ...
- info.plist
更新了Xcode8 以及 iOS10,App访问用户的相机.相册.麦克风.通讯录的权限都需要重新进行相关的配置,不然在Xcode8中打开编译的话会直接crash. 需要在info.plist中添加Ap ...
- 安装 Flex2packagebeta_1.994
下载文件 解压到/var/root/Media/Cydia/AutoInstall/这个路径重启手机,Cydia会自动安装好DEB文件的 patch路径 下载 /private/var/mobile/ ...
- Linux see 网卡当前流量
linux see网卡的当前流量 sar –n DEV 1 2 命令后面1 2 意思是:每一秒钟取1次值,取2次. DEV显示网络接口信息 -n参数很有用,他有6个不同的开关:DEV | EDEV ...
- OpenERP Client Error
SyntaxError: JSON.parse: unexpected end of data http/mydomain:8069/web/webclient/js:23114 Solutions: ...
- SpringBoot自定义HttpMessageConverter
Spring就是一个大大的插线板,上面插着各种各样的Bean. SpringBoot大大简化了Spring的配置,将原来放在XML中的配置大量的在代码中使用注解实现.这么做有利有弊,总体上利大于弊. ...