首先看一个构造函数User,我们在调用User创建一个实例的的时候,一般都是要写上new操作符的。在这里说明一下,如果使用new关键字调用构造函数,那么构造函数里面的this总是是指向一个全新的对象(即User的实例),如果不是使用new的话,那么this就指向global对象。User构造函数的定义如下:
function User(name, passwordHash) {
this.name = name;
this.passwordHash = passwordHash;
}
 User构造函数的正确的调用方法应该如下:
var u = new User("baravelli", "d8b74df393528d51cd19980ae0aa028e");
但是,假如调用者因为粗心,忘记了加上new关键字来调用,那结果会怎样呢?我们一起来测试一下:
var u = User("baravelli", "d8b74df393528d51cd19980ae0aa028e");
u; // undefined
this.name; // "baravelli"
this.passwordHash; // "d8b74df393528d51cd19980ae0aa028e"
 
结果构造函数竟然返回了undefined!!这也很正常的,因为不用new关键字,直接调用他的话,那就跟调用普通函数没有任何区别了,而User里面又没有return语句,所以返回值当然是undefined了。更加糟糕的是,如果不加new调用,User的里面的this就会指向全局对象了,那么它就会破坏全局对象,试想一下,假如全局对象本身就存在了name和passwordHash这两个变量,那么他们的值就会被修改了,这个危害是很大的。
 
如果,构造函数User里面开启了ES5的严格模式,那么不使用new操作符就会因为this绑定失败而抛出错误(注意:严格模式下是不允许this指向全局对象的),如下:
function User(name, passwordHash) {
"use strict";
this.name = name;
this.passwordHash = passwordHash;
} var u = User("baravelli", "d8b74df393528d51cd19980ae0aa028e");
// error: this is undefined
这样的话,会抛出一个类型错误// error: this is undefined。但是,这个构造函数依然是很脆弱的,因为它只有在加new操作符的时候才可以正常工作。假如我们实现了一个构造函数,加不加new关键字都可以正常工作那就健壮多了!其实,实现起来也并不太难,我们只要在User构造函数里面判断this是否指向User的实例就行了,如果不是就创建一个User实例,如下:
function User(name, passwordHash) {
if (!(this instanceof User)) {
return new User(name, passwordHash);
}
this.name = name;
this.passwordHash = passwordHash;
}
 
现在,不管你用不用new关键字来调用构造函数,他都可以正常工作了,测试一下:
var x = User("baravelli", "d8b74df393528d51cd19980ae0aa028e");
var y = new User("baravelli",
"d8b74df393528d51cd19980ae0aa028e");
x instanceof User; // true
y instanceof User; // true
 
  但是上述实现方法还具有一个缺点,因为它两次调用了User构造函数(在不使用new关键字的时候),所以,降低了性能!而且,还有一个问题,就是对于可变参数的构造函数,它实现起来就会很困难的了。一种较优的办法就是借助于ES5的Object.create方法:
function User(name, passwordHash) {
var self = this instanceof User ? this : Object.create(User.prototype);
self.name = name;
self.passwordHash = passwordHash;
return self;
}
 这种方法,借助了Object.create方法,把User.prototype作为参数,创建了一个继承了User的新对象。但是,这种方法也是有缺陷的,我们前面已经说过 了,Object.create是ES5的新标准,在一些旧的环境下可能无法工作。所以,我们还要判断Object.create是否存在。,如果不存在,则手动的去实现它:
if (typeof Object.create === "undefined") {
Object.create = function(prototype) {
function C() { }
C.prototype = prototype;
return new C();
};
}
最后,需要提醒的是,如果你的构造函数一定要使用new关键字的,那么必须要写文档说明,以免别人调用的时候没有用new操作符,产生意想不到的结果!

如何优化JavaScript的构造函数的更多相关文章

  1. 优化javaScript代码,提高执行效率

    今天看完书,总结了一下可以如何优化 JavaScript . 1.合并js文件 为优化性能,可以把多个js文件(css文件也可以)合并成极少数大文件.跟十个5k的js文件相比,合并成一个50k的文件更 ...

  2. 深入理解Javascript中构造函数和原型对象的区别

    在 Javascript中prototype属性的详解 这篇文章中,详细介绍了构造函数的缺点以及原型(prototype),原型链(prototype chain),构造函数(constructor) ...

  3. Javascript中构造函数的返回值问题和new对象的过程

    首先明确一点:javascript中构造函数是不需要有返回值的,这一点跟java很类似.可以认为构造函数和普通函数的最大差别就是:构造函数中没有return语句,普通函数可以有return语句:构造函 ...

  4. 解决JavaScript中构造函数浪费内存的问题!

    解决JavaScript中构造函数浪费内存的问题! 把构造函数中的公共的方法放到构造函数的原型对象上! // 构造函数的问题! function Gouzaohanshu(name, age, gen ...

  5. Javascript正则构造函数与正则表达字面量&&常用正则表达式

    本文不讨论正则表达式入门,即如何使用正则匹配.讨论的是两种创建正则表达式的优劣和一些细节,最后给出一些常用正则匹配表达式. Javascript中的正则表达式也是对象,我们可以使用两种方法创建正则表达 ...

  6. JavaScript使用构造函数获取变量的类型名

    在JavaScript中,如何准确获取变量的类型名是一个经常使用的问题. 但是常常不能获取到变量的精确名称,或者必须使用jQuery 中的方法,这里 我通过 typeof ,jQuery.type 和 ...

  7. Javascript中构造函数与new命令

    典型的面向对象编程语言(比如C++和Java),存在“类”(class)这个概念.所谓“类”就是对象的模板,对象就是“类”的实例.但是,在JavaScript语言的对象体系,不是基于“类”的,而是基于 ...

  8. Javascript中构造函数与new命令2

    典型的面向对象编程语言(比如C++和Java),存在"类"(class)这个概念.所谓"类"就是对象的模板,对象就是"类"的实例.但是,在J ...

  9. Javascript将构造函数扩展为简单工厂

    一般而言,在Javascript中创建对象时需要使用关键字new(按构造函数去调用),但是某些时候,开发者希望无论new关键字有没有被显式使用,构造函数都可以被正常调用,即构造函数同时还具备简单工厂的 ...

随机推荐

  1. DevExpress v18.1新版亮点——DevExtreme篇(二)

    用户界面套包DevExpress v18.1日前终于正式发布,本站将以连载的形式为大家介绍各版本新增内容.本文将介绍了DevExtreme JavaScript Controls v18.1 的新功能 ...

  2. countdownlatch 和 CyclicBarrier 和 Semaphore

    cdl用的是aqs,共享的是aqs那个volatile的state,阻塞线程列表用的也是aqs的 cb用的是reentrantlock+condition,当然rel用的也是aqs不过不同的是用的是互 ...

  3. connection reset 分析解决(转载)

    文章转自:https://my.oschina.net/xionghui/blog/508758;记录下来以便以后复习查阅; 在使用HttpClient调用后台resetful服务时,“Connect ...

  4. 2019-02-25 EST 科技文翻译

    The Definition of Theme and Rheme The point of departure is equally presented to the speaker and to ...

  5. python day02 作业答案

    1. (1).false   (2).false 2. (1).8  (2).4 3. (1).6  (2).3  (3).false (4).3   (5).true   (6).true  (7) ...

  6. win10自动锁屏问题

    电源管理里面无论如何设置自动关闭屏幕时间.自动睡眠和休眠的时间,以及关闭屏保等,在2分钟(确切是2分多一点)后电脑自动睡眠. 这是系统无人值守时睡眠时间的设定,默认是两分钟.解决方法:1.运行注册表管 ...

  7. Ubuntu 录制视频并制作成gif图

    最近在github中添加项目实现效果时需要用到gif图,在网上搜了一些工具和教程,会发现windows系统比ubuntu多很多,经过实际验证以下这种方法可以实现gif图的录制与制作,具体方法如下:   ...

  8. Python基础2 字符编码和逻辑运算符

    编码 AscII码 :标准ASCII码是采用7位二进制码来编码的,最高为0,没有0000 0000,所以就是2**7-1=127个字符 , 当用1个字节(8位二进制码)来表示ASCII码时,就在最高位 ...

  9. Subsequence Count 2017ccpc网络赛 1006 dp+线段树维护矩阵

    Problem Description Given a binary string S[1,...,N] (i.e. a sequence of 0's and 1's), and Q queries ...

  10. Gym101002 2016NAIPC(队内第7次训练)

    (由于先看的最后一题,然后又一直WA,导致这场有点爆炸,我背锅. A .Fancy Antiques 题意: 选择最多k个商店,买n个物品,每个物品分别对应两个店售卖,求最小花费是多少.n<10 ...