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

当使用User函数创建一个构造函数时,程序依赖于调用者是否记得使用new操作符来调用该构造函数。注意的是,该函数假设接收者是一个全新的对象。
如果调用者忘记使用new关键字,那么函数的接收者将是全局对象。

// undefined
var u = User('zhangsan', 'djkgjk23lkl4332l3k289ds');

该函数不但会返回无意义的undefined,而且会灾难性地创建全局变量name和passwordHash。

如果将User函数定义为ES5的严格代码,那么接收者默认认为是undefined

function User(name, passwordHash) {
'use strict'; // Cannot set property 'name' of undefined
this.name = name;
this.passwordHash = passwordHash;
} var u = User('zhangsan', 'djkgjk23lkl4332l3k289ds');

在这种情况下,这种错误的调用会导致一个即使错误:Cannot set property 'name' of undefined

一个更为健壮的方式是提供一个不管怎样调用都工作如构造函数的函数。实现这样的函数一个简单的方法是检查函数的接收者是否是一个正确的User实例。

// 检查函数的接受者是否是一个正确的User实例
// 缺点,不适应于可变参数函数
function User(name, passwordHash) {
if (!(this instanceof User)) {
return new User(name, passwordHash);
}
this.name = name;
this.passwordHash = passwordHash;
}
// User {name: "zhangsan", passwordHash: "djkgjk23lkl4332l3k289ds"}
var u = User('zhangsan', 'djkgjk23lkl4332l3k289ds');

这种模式的一个缺点是它需要额外的函数调用,而且不适应可变参数函数(因为没有直接模拟apply方法将可变参数函数作为构造函数调用的方法)。一种更为高效的方式是利用ES5的Object.create函数。

function User(name, passwordHash) {
var self = this instanceof User ? this : Object.create(User.prototype);
console.log(self);
self.name = name;
self.passwordHash = passwordHash;
return self;
}
// User {name: "zhangsan", passwordHash: "djkgjk23lkl4332l3k289ds"}
var u = User('zhangsan', 'djkgjk23lkl4332l3k289ds');

Object.create需要一个原型对象作为参数,并返回一个继承自该原型对象的新对象。

Object.create只有在ES5环境下才是有效的,这里提供了一个兼容版的。

if (typeof Object.create === 'undefined') {
Object.create = function(prototype) {
var C = function() {};
C.prototype = prototype;
return new C;
}
};

这里只实现了单参数版本的Object.create函数。

参考:编写高质量JavaScript代码的68个有效方法

JS使构造函数与new操作符无关的更多相关文章

  1. [Effective JavaScript 笔记]第33条:使构造函数与new操作符无关

    当使用函数作为一个构造函数时,程序依赖于调用者是否记得使用new操作符来调用该构造函数.注意:该函数假设接收者是一个全新的对象. 一个例子 function User(name,pwd){ this. ...

  2. JS中构造函数和普通函数有什么区别

    JS中构造函数有普通函数有什么区别? 1.一般规则 构造函数都应该以 一个大写字母开头,eg: function Person(){...} 而非构造函数则应该以一个小写字母开头,eg: functi ...

  3. js 时间构造函数

    js 时间构造函数,js中没有类似ToString("yyyy-mm-dd HH:mm:ss") 的方法,但是可以用下面的方式来初始化 var cdate = new Date(& ...

  4. C++学习基础六——复制构造函数和赋值操作符

    1.什么是复制构造函数 复制构造函数:是构造函数,其只有一个参数,参数类型是所属类的类型,且参数是一个const引用. 作用:将本类的成员变量赋值为引用形参的成员变量. 2.什么是赋值操作符 赋值操作 ...

  5. C++中复制构造函数和赋值操作符

    先看一个例子: 定义了一个类:

  6. C++在单继承、多继承、虚继承时,构造函数、复制构造函数、赋值操作符、析构函数的执行顺序和执行内容

    一.本文目的与说明 1. 本文目的:理清在各种继承时,构造函数.复制构造函数.赋值操作符.析构函数的执行顺序和执行内容. 2. 说明:虽然复制构造函数属于构造函数的一种,有共同的地方,但是也具有一定的 ...

  7. js高级——构造函数,实例对象和原型对象——prototype、__proto__和constructor构造器

    一.前言 了解JavaScript面向对象,需要先了解三个名词: 构造函数,实例对象和原型对象. 注意:JavaScript中没有类(class)的概念,取而代之的是构造函数,两者类似却又有很大的差别 ...

  8. [c++基础]3/5原则--拷贝构造函数+拷贝赋值操作符

    /* * main.cpp * * Created on: Apr 7, 2016 * Author: lizhen */ #include <iostream> #include &qu ...

  9. JS基础——构造函数VS原型

    JS是一种基于对象的语言.在使用过程中不免遇到复制对象的问题.但通常我们採用的直接赋值'obj1=obj2'这样的做法会出现数据覆盖问题. 也就是对象引用过程中引用地址一致.导致对象数据被改动的问题. ...

随机推荐

  1. ruby + watir 自动化上传图片文件解决方案

    watir自动化捕获上传图片元素: require 'watir' include Watir require 'test/unit' class TC_recorded < Test::Uni ...

  2. LinkedHashMap及其源码分析

    以下内容基于jdk1.7.0_79源码: 什么是LinkedHashMap 继承自HashMap,一个有序的Map接口实现,这里的有序指的是元素可以按插入顺序或访问顺序排列: LinkedHashMa ...

  3. Effective Java Index

    Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...

  4. [MySQL Reference Manual] 4 MYSQL Program

    4 MYSQL Program 目录 4 MYSQL Program 4.3 MySQL Server和Server启动程序 4.3.1 mysqld 4.3.2 mysqld_safe 4.3.3 ...

  5. 通过mdf ldf文件还原数据库

    新建查询,执行如下语句: EXEC sp_attach_db @dbname = 'xxx', /*数据库名称*/ @filename1 = 'D:\数据库备份\预发布\201611241045 测试 ...

  6. sql server 警报管理,实时监听数据库动向,运筹帷幄之中

    工作这么多年了,无论是身边的同学还是同事,发现只要搞程序员的都有一个通病---懒.懒到谁都不愿意加班,尤其是"义务"加班.即使大家都不愿意加班,但是很多时候项目赶着上线或者上线之后 ...

  7. my_strcat()

    char* my_strcat(char* S1,const char* S2){ //严格符合strcat()的接口形式,需要的S1空间是两个字符串空间总和-1. int i=0,j=0; whil ...

  8. /proc/interrupts 统计2.6.38.8与3.10.25差异

    eth4进,eth5出 linux-3.10.25 67:          2          3          2          3   PCI-MSI-edge     eth468: ...

  9. Puppet3在CentOS6.5集群下的安装

    环境:3台主机, IP分别为10.211.55.11.12.13 puppet master安装在10.211.55.11 puppet agent安装在10.211.55.11.12.13 1.安装 ...

  10. AI(Adobe Illustrator)简单入门——骷髅

    成果: 步骤如下: 一.椭圆工具画正圆 按住shift+alt画一个正圆. 二.圆角矩形工具画矩形 用圆角矩形工具画一个矩形,然后全选水平垂直对齐. 三.画眼睛 利用椭圆工具画一只眼睛,然后按住alt ...