JavaScript语言对象:基础构造函数,运算符“新”

构造函数,运算符“新”

常规{...}语法允许创建一个对象。但是通常我们需要创建许多类似的对象,例如多个用户或菜单项等等。z7Q码友部落

可以使用构造函数和"new"运算符来完成z7Q码友部落

构造函数

从技术上讲,构造函数是常规函数。但是有两个约定:z7Q码友部落

  1. 它们首先以大写字母命名。
  2. 它们只能由"new"运算符执行

例如:z7Q码友部落

function User(name) {
  this.name = name;
  this.isAdmin = false;
}

let user = new User("Jack");

alert(user.name); // Jack
alert(user.isAdmin); // false

使用执行函数时new,它将执行以下步骤:z7Q码友部落

  1. 将创建一个新的空对象并将其分配给this
  2. 功能体执行。通常,它会修改this为其添加新属性。
  3. this返回的值

换句话说,new User(...)执行以下操作:z7Q码友部落

function User(name) {
  // this = {};  (implicitly)

  // add properties to this
  this.name = name;
  this.isAdmin = false;

  // return this;  (implicitly)
}

因此let user = new User("Jack")给出与以下结果相同的结果:z7Q码友部落

let user = {
  name: "Jack",
  isAdmin: false
};

现在,如果要创建其他用户,可以调用new User("Ann")new User("Alice")依此类推。比每次都使用文字短得多,而且易于阅读。z7Q码友部落

那是构造函数的主要目的–实现可重用的对象创建代码。z7Q码友部落

让我们再次注意–从技术上讲,任何函数都可以用作构造函数。也就是说:任何函数都可以通过运行new,它将执行上面的算法。“大写字母优先”是一个常见的约定,以明确说明要使用来运行功能newz7Q码友部落

新函数(){…}

如果我们有很多关于创建单个复杂对象的代码行,则可以将它们包装在构造函数中,如下所示:z7Q码友部落

let user = new function() {
  this.name = "John";
  this.isAdmin = false;

  // ...other code for user creation
  // maybe complex logic and statements
  // local variables etc
};

构造函数无法再次调用,因为它不会保存在任何地方,只是创建和调用。因此,此技巧旨在封装构造单个对象的代码,而无需将来重用。z7Q码友部落

构造器模式测试:new.target

进阶的东西

很少使用本节中的语法,除非您想了解所有内容,否则请跳过该语法。z7Q码友部落

在函数内部,我们可以new使用特殊new.target属性检查是否调用了该函数z7Q码友部落

对于常规调用,它是未定义的,如果与调用,则等于该函数newz7Q码友部落

function User() {
  alert(new.target);
}

// without "new":
User(); // undefined

// with "new":
new User(); // function User { ... }

可以在函数内部使用该函数来知道是使用new“构造函数模式”,还是不使用“常规模式”来调用它。z7Q码友部落

我们还可以同时进行new常规调用和常规调用,如下所示:z7Q码友部落

function User(name) {
  if (!new.target) { // if you run me without new
    return new User(name); // ...I will add new for you
  }

  this.name = name;
}

let john = User("John"); // redirects call to new User
alert(john.name); // John

有时在库中使用此方法以使语法更灵活。这样,人们可以使用或不使用来调用该函数new,并且该函数仍然有效。z7Q码友部落

不过,在任何地方使用new可能都不是一件好事,因为省略它会使发生的事情变得不太明显。随着new我们都知道,正在创建新的对象。z7Q码友部落

构造者的回报

通常,构造函数没有return语句。他们的任务是将所有必要的内容写入this,然后它自动成为结果。z7Q码友部落

但是,如果有一条return声明,那么规则很简单:z7Q码友部落

  • 如果return使用物件呼叫,则会传回而不是this
  • 如果return使用原语调用,则将其忽略。

换句话说,return使用对象返回该对象,在所有其他情况下this将返回该对象z7Q码友部落

例如,这里通过返回一个对象return覆盖thisz7Q码友部落

function BigUser() {

  this.name = "John";

  return { name: "Godzilla" };  // <-- returns this object
}

alert( new BigUser().name );  // Godzilla, got that object

这是一个空的示例return(或者我们可以在其后放置一个原语,没关系):z7Q码友部落

function SmallUser() {

  this.name = "John";

  return; // <-- returns this
}

alert( new SmallUser().name );  // John

通常,构造函数没有return声明。在这里,我们提到返回对象的特殊行为主要是出于完整性的考虑。z7Q码友部落

省略括号

顺便说一句,new如果没有参数,我们可以在后面省略括号z7Q码友部落

let user = new User; // <-- no parentheses
// same as
let user = new User();

此处省略括号不被视为“好样式”,但是规范允许语法。z7Q码友部落

构造函数中的方法

使用构造函数创建对象具有很大的灵活性。构造函数可以具有定义如何构造对象以及放入对象的参数。z7Q码友部落

当然,我们this不仅可以添加属性,还可以添加方法。z7Q码友部落

例如,new User(name)下面使用给定name和方法创建一个对象sayHiz7Q码友部落

function User(name) {
  this.name = name;

  this.sayHi = function() {
    alert( "My name is: " + this.name );
  };
}

let john = new User("John");

john.sayHi(); // My name is: John

/*
john = {
   name: "John",
   sayHi: function() { ... }
}
*/

为了创建复杂的对象,有一个更高级的语法,class,我们将在后面介绍。z7Q码友部落

概要

  • 构造函数或简而言之,构造函数是常规函数,但是有一个共同的协议,即首先用大写字母命名它们。
  • 构造函数只能使用调用new这样的调用意味着this在开始处创建一个空值,并在结束时返回填充的值。

我们可以使用构造函数来创建多个相似的对象。z7Q码友部落

JavaScript为许多内置语言对象提供了构造函数:例如Date日期,Set集合以及我们计划学习的其他对象z7Q码友部落

对象,我们会回来的!

在本章中,我们仅介绍有关对象和构造函数的基础知识。在下一章中,它们对于了解更多有关数据类型和功能的信息至关重要。z7Q码友部落

了解了这一点之后,我们将返回到对象,并在“原型,继承和类”一章中深入介绍它们。z7Q码友部落

任务

两种功能–一个对象

z7Q码友部落
重要性:2

是否有可能创建函数ABnew A()==new B()z7Q码友部落

function A() { ... }
function B() { ... }

let a = new A;
let b = new B;

alert( a == b ); // true

如果是,请提供其代码示例。z7Q码友部落

z7Q码友部落

创建新的计算器

z7Q码友部落
重要性:5

创建一个构造函数Calculator,该函数使用3种方法创建对象:z7Q码友部落

  • read()要求使用两个值prompt,并在对象属性中记住它们。
  • sum() 返回这些属性的总和。
  • mul() 返回这些属性的乘积。

例如:z7Q码友部落

let calculator = new Calculator();
calculator.read();

alert( "Sum=" + calculator.sum() );
alert( "Mul=" + calculator.mul() );

运行演示z7Q码友部落

用测试打开一个沙箱。z7Q码友部落

z7Q码友部落

创建新的累加器

z7Q码友部落
重要性:5

创建一个构造函数Accumulator(startingValue)z7Q码友部落

它创建的对象应:z7Q码友部落

  • 将“当前值”存储在属性中value起始值设置为构造函数的参数startingValue
  • read()方法prompt应用于读取新数字并将其添加到中value

换句话说,该value属性是所有用户输入值与初始值的总和 startingValuez7Q码友部落

这是代码的演示:z7Q码友部落

let accumulator = new Accumulator(1); // initial value 1

accumulator.read(); // adds the user-entered value
accumulator.read(); // adds the user-entered value

alert(accumulator.value); // shows the sum of these values