博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Effective JavaScript Item 33 让构造函数不再依赖newkeyword
阅读量:6197 次
发布时间:2019-06-21

本文共 2141 字,大约阅读时间需要 7 分钟。

本系列作为EffectiveJavaScript的读书笔记。

 

在将function当做构造函数使用时,须要确保该函数是通过newkeyword进行调用的。

function User(name, passwordHash) {	this.name = name;	this.passwordHash = passwordHash;}

假设在调用上述构造函数时。忘记了使用newkeyword。那么:

var u = User("baravelli", "d8b74df393528d51cd19980ae0aa028e");u; // undefinedthis.name; // "baravelli"this.passwordHash; // "d8b74df393528d51cd19980ae0aa028e"

能够发现得到的uundefined。而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; // truey 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语言的一些约定俗成)

 

总结:

  1. 使用Object.create来保证一个函数确实是被当做一个构造函数进行调用的,不管newkeyword是否被使用了。

  2. 对于作为构造函数的函数。在文档中指明这一点来保证其它用户可以正确的使用它。

转载地址:http://jvjca.baihongyu.com/

你可能感兴趣的文章
分享:我的2012
查看>>
x264简介
查看>>
分享:一个支持并发, 支持异步/同步, 支持http/https, 支持续传的avhttp库
查看>>
Android学习笔记28:对话框Dialog控件的使用
查看>>
搬家到CSDN通知
查看>>
rand5()构造rand7() [转]
查看>>
ECSHOP增加模板页的方法
查看>>
java String 中length()的长度计算,substring(0,n);的截取长度计算
查看>>
假数据绑定列表
查看>>
说到作到,HADOOP双节点配置成功
查看>>
URL中的"#"
查看>>
拦截器、方法-浅谈Struts2拦截器的原理与实现-by小雨
查看>>
广播与P2P通道(上) -- 问题与方案
查看>>
测试单元测试javascript单元测试及框架介绍
查看>>
SQL 必知必会·笔记<3>过滤数据
查看>>
Android布局中涉及的一些属性
查看>>
网站编程安全之更改文章时注意事项
查看>>
Java:多线程,CountDownLatch同步器
查看>>
SCP命令小例子
查看>>
easyui简单使用
查看>>