有效的JavaScript:使您的构造函数成为新的不可知函数

有效的JavaScript:使您的构造函数成为新的不可知函数,javascript,oop,Javascript,Oop,我最近一直在读《高效JavaScript》,我遇到了这个问题 作者解释了使构造函数成为新的不可知函数的重要性,因为如果开发人员忘记使用“new”关键字调用构造函数,“this”指的是“Window”。这是有道理的。让我困惑的是他实施的目的 他建议你这样设置构造器 var Person = function(name, age){ var that = this instanceof Person ? this : Object.create(Person.prototype); that

我最近一直在读《高效JavaScript》,我遇到了这个问题

作者解释了使构造函数成为新的不可知函数的重要性,因为如果开发人员忘记使用“new”关键字调用构造函数,“this”指的是“Window”。这是有道理的。让我困惑的是他实施的目的

他建议你这样设置构造器

var Person = function(name, age){
  var that = this instanceof Person ? this : Object.create(Person.prototype);
  that.name = name;
  that.age = age;
  return that;
}
这是有道理的。检查“this”是否是Person的实例,这意味着它是用“new”关键字调用的。如果不是,则创建一个与“this”执行相同操作的新对象,并返回该对象

我的问题是。如果您正在设置一个与“this”执行相同操作的新对象,我们就不能不担心是否通过前面的“this”和创建新对象来使用new调用构造函数

var Person = function(name, age){
  var that = Object.create(Person.prototype);
  that.name = name;
  that.age = age;
  return that;
}
为什么要担心“这个”和“新的”,为什么不总是像上面那样创建我们的构造函数呢

为什么要担心“这个”和“新的”,为什么不总是像上面那样创建我们的构造函数呢

因为只写更简洁

function Person(name, age) {
    this.name = name;
    this.age = age;
}
new
是在
Object.create
(在旧浏览器中不可用)之前发明的,并成为标准模式。大多数人已经习惯了它,所以他们不必费心在(!(Person的这个实例))返回新的Person(姓名、年龄)检查中包含

如果您正在设置一个与“this”执行相同操作的新对象,我们就不能不担心是否通过前面的“this”和创建新对象来使用new调用构造函数

不,您并不总是知道如何创建新对象
Person的此实例
也适用于从
Person.prototype
继承的任何其他实例,并且允许:


如果您选择始终返回一个新对象,
Person.call(this)
将不可能实现。

是的,效果相同,但是,它会再分配一个对象。构造器是用来与new一起使用的,这种技术可以避免程序员忘记了new的情况


如果你问我的话,最好在后一种情况下抛出一个异常。

是的,这是一种方法,尽管从技术上讲,当使用
new
调用时,会创建两个对象,尽管你只使用了一个。@tylermcginis:one因为它是使用
new
调用的,另一个是通过调用
Object.create()
。您只是忽略了从
new
@Nit创建的一个:我不想重新键入它。如果你能做得更彻底一点,我会给你+1。@dandavis:不,它仍然继承自
Person.prototype
。这是同一个构造,只是使用了不同的语法。@dandavis:如果重新定义了
Person
,这不会破坏继承。自然地更新到新的
Person.prototype
不会反映在已经构造的对象中,但是给函数一个名称不会改变这一事实,除非您正在谈论在构造函数中为
Person.prototype
添加属性,这将是非常奇怪的
如果您选择始终返回一个新对象,那么这是不可能的。“为什么会有不同?返回值被忽略,并且Person的
this instanceof成功,因此
that===this
。我不明白你在这里得到了什么。@CookieMonester:它适用于他的第一个三元运算符构造函数,但不适用于
var that=Object.create(Person.prototype)
function Employee(name, age, salary) {
    Person.call(this, name, age);
    this.salary = salary;
}
Employee.prototype = Object.create(Person.prototype);