【问题标题】:Effective JavaScript: Making your Constructor Function new-agnostic有效的 JavaScript:使您的构造函数与新无关
【发布时间】:2014-06-03 16:06:45
【问题描述】:

我最近一直在阅读“有效的 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”调用构造函数并创建新对象。

var Person = function(name, age){
  var that = Object.create(Person.prototype);
  that.name = name;
  that.age = age;
  return that;
}

为什么要担心“this”和“new”,为什么不总是像上面那样创建我们的构造函数?

【问题讨论】:

  • 是的,这是一种方法,虽然从技术上讲,当使用 new 调用时,虽然您只使用一个对象,但会创建两个对象。
  • @TylerMcGinnis:一个是因为它是使用new 调用的,另一个是通过调用Object.create()。您只是忽略了从new 创建的那个。
  • @Nit:我不想重新输入它。如果你能做到,但让它更彻底,我会给你+1。
  • @dandavis:不,它仍然继承自Person.prototype。这是相同的结构,只是使用了不同的语法。
  • @dandavis:如果 Person 被重新定义,那不会破坏继承。对新的 Person.prototype 的自然更新不会反映在已经构建的对象中,但是给函数命名不会改变这一事实,除非您正在谈论向 Person.prototype 添加属性 inside 构造函数,这会很奇怪。

标签: javascript oop


【解决方案1】:

为什么要担心“this”和“new”,为什么不总是像上面那样创建我们的构造函数?

因为只写更简洁

function Person(name, age) {
    this.name = name;
    this.age = age;
}

new 是在Object.create 之前发明的(在旧版浏览器中不可用)并成为标准模式。大多数人都已经习惯了,以至于他们都懒得写if (!(this instanceof Person)) return new Person(name, age) 支票。

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

不,您并不总是知道如何创建新对象。 this instanceof Person 也适用于从 Person.prototype 继承的任何其他东西,并且确实允许 class inheritance

function Employee(name, age, salary) {
    Person.call(this, name, age);
    this.salary = salary;
}
Employee.prototype = Object.create(Person.prototype);

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

【讨论】:

  • “如果您选择始终返回一个新对象,Person.call(this) 将不可能实现。” 为什么会有不同?返回值被忽略,this instanceof Person 成功,所以that === this。我不明白你在这里的意思。
  • @cookiemonster:它适用于他的第一个带有三元运算符的构造函数,但不适用于第二个构造函数中的var that = Object.create(Person.prototype);
【解决方案2】:

是的,效果是一样的,只是多分配了一个对象。构造函数旨在与 new 一起使用,这种技术可以解决程序员忘记 new 的情况。

如果你问我,在后一种情况下抛出异常会更好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-10
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多