>  기사  >  웹 프론트엔드  >  JavaScript 생성자와 "new" 연산자에 대한 자세한 설명

JavaScript 생성자와 "new" 연산자에 대한 자세한 설명

coldplay.xixi
coldplay.xixi앞으로
2020-11-13 17:39:522493검색

javascript이 칼럼에서는 "new" 연산자를 소개합니다.

JavaScript 생성자와 "new" 연산자에 대한 자세한 설명

생성자 및 연산자 "new"

일반 {...} 구문을 사용하면 객체를 생성할 수 있습니다. 그러나 여러 사용자나 메뉴 항목 등과 같은 유사한 개체를 많이 만들어야 하는 경우가 많습니다. {...} 语法允许创建一个对象。但是我们经常需要创建许多类似的对象,例如多个用户或菜单项等。

这可以使用构造函数和 "new" 操作符来实现。

构造函数

构造函数在技术上是常规函数。不过有两个约定:

  1. 它们的命名以大写字母开头。
  2. 它们只能由 "new" 操作符来执行。

例如:

function User(name) {  this.name = name;  this.isAdmin = false;
}let user = new User("Jack");

alert(user.name); // Jackalert(user.isAdmin); // false复制代码

当一个函数被使用 new 操作符执行时,它按照以下步骤:

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

换句话说,new User(...) 做的就是类似的事情:

function User(name) {  // this = {};(隐式创建)

  // 添加属性到 this
  this.name = name;  this.isAdmin = false;  // return this;(隐式返回)}复制代码

所以 new User("Jack") 的结果是相同的对象:

let user = {  name: "Jack",  isAdmin: false};复制代码

现在,如果我们想创建其他用户,我们可以调用 new User("Ann")new User("Alice") 等。比每次都使用字面量创建要短得多,而且更易于阅读。

这是构造器的主要目的 —— 实现可重用的对象创建代码。

让我们再强调一遍 —— 从技术上讲,任何函数都可以用作构造器。即:任何函数都可以通过 new 来运行,它会执行上面的算法。“首字母大写”是一个共同的约定,以明确表示一个函数将被使用 new 来运行。

new function() { ... }

如果我们有许多行用于创建单个复杂对象的代码,我们可以将它们封装在构造函数中,像这样:

let user = new function() {  this.name = "John";  this.isAdmin = false;  // ……用于用户创建的其他代码
  // 也许是复杂的逻辑和语句
  // 局部变量等};复制代码

构造器不能被再次调用,因为它不保存在任何地方,只是被创建和调用。因此,这个技巧旨在封装构建单个对象的代码,而无需将来重用。

构造器模式测试:new.target

进阶内容:

本节涉及的语法内容很少使用,除非你想了解所有内容,否则你可以直接跳过该语法。

在一个函数内部,我们可以使用 new.target 属性来检查它是否被使用 new 进行调用了。

对于常规调用,它为空,对于使用 new 的调用,则等于该函数:

function User() {
  alert(new.target);
}// 不带 "new":User(); // undefined// 带 "new":new User(); // function User { ... }复制代码

它可以被用在函数内部,来判断该函数是被通过 new 调用的“构造器模式”,还是没被通过 new 调用的“常规模式”。

我们也可以让 new 调用和常规调用做相同的工作,像这样:

function User(name) {  if (!new.target) { // 如果你没有通过 new 运行我
    return new User(name); // ……我会给你添加 new
  }  this.name = name;
}let john = User("John"); // 将调用重定向到新用户alert(john.name); // John复制代码

这种方法有时被用在库中以使语法更加灵活。这样人们在调用函数时,无论是否使用了 new,程序都能工作。

不过,到处都使用它并不是一件好事,因为省略了 new 使得很难观察到代码中正在发生什么。而通过 new 我们都可以知道这创建了一个新对象。

构造器的 return

通常,构造器没有 return 语句。它们的任务是将所有必要的东西写入 this,并自动转换为结果。

但是,如果这有一个 return 语句,那么规则就简单了:

  • 如果 return 返回的是一个对象,则返回这个对象,而不是 this
  • 如果 return 返回的是一个原始类型,则忽略。

换句话说,带有对象的 return 返回该对象,在所有其他情况下返回 this

例如,这里 return 通过返回一个对象覆盖 this

function BigUser() {  this.name = "John";  return { name: "Godzilla" };  // <-- 返回这个对象}

alert( new BigUser().name );  // Godzilla,得到了那个对象复制代码

这里有一个 return 为空的例子(或者我们可以在它之后放置一个原始类型,没有什么影响):

function SmallUser() {  this.name = "John";  return; // <-- 返回 this}

alert( new SmallUser().name );  // John复制代码

通常构造器没有 return 语句。这里我们主要为了完整性而提及返回对象的特殊行为。

省略括号

顺便说一下,如果没有参数,我们可以省略 new

이는 생성자와 "new" 연산자를 사용하여 달성할 수 있습니다.

생성자

생성자는 기술적으로 일반적인 함수입니다. 하지만 두 가지 규칙이 있습니다:

  1. 이름은 대문자로 시작합니다.
  2. "new" 연산자로만 실행할 수 있습니다.

예:

let user = new User; // <-- 没有参数// 等同于let user = new User();复制代码
🎜 new 연산자를 사용하여 함수가 실행되면 다음 단계를 따릅니다. 🎜
  1. 새 빈 객체는 다음과 같습니다. 에 생성 및 할당되었습니다.
  2. 함수 본문이 실행됩니다. 일반적으로 를 수정하여 새 속성을 추가합니다.
  3. this의 값을 반환합니다.
🎜즉, new User(...)는 다음과 같은 작업을 수행합니다. 🎜
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() { ... }
}
*/复制代码
🎜그래서 new User("Jack") 결과는 다음과 같습니다. code>는 동일한 개체입니다. 🎜
function A() { ... }function B() { ... }let a = new A;let b = new B;

alert( a == b ); // true复制代码
🎜이제 다른 사용자를 생성하려면 new User("Ann"), new User("Alice")를 호출하면 됩니다. 코드> 등 매번 리터럴 생성을 사용하는 것보다 훨씬 짧고 읽기 쉽습니다. 🎜🎜이것이 생성자의 주요 목적입니다. 재사용 가능한 객체 생성 코드를 구현하는 것입니다. 🎜🎜다시 말해 보겠습니다. 기술적으로는 모든 함수를 생성자로 사용할 수 있습니다. 즉, 모든 함수는 위의 알고리즘을 실행하는 new를 통해 실행될 수 있습니다. "대문자화"는 함수가 new를 사용하여 실행될 것임을 분명히 하기 위한 일반적인 규칙입니다. 🎜

new function() { ... }

🎜단일 복잡한 객체를 생성하는 코드 줄이 많은 경우 다음과 같이 생성자에 이를 캡슐화할 수 있습니다. 이: 🎜
let calculator = new Calculator();
calculator.read();

alert( "Sum=" + calculator.sum() );
alert( "Mul=" + calculator.mul() );复制代码
🎜 생성자는 어디에도 저장되지 않고 생성되고 호출되기 때문에 다시 호출할 수 없습니다. 따라서 이 팁은 나중에 재사용할 필요 없이 단일 개체를 빌드하는 코드를 캡슐화하기 위한 것입니다. 🎜

생성자 패턴 테스트: new.target🎜
🎜고급 콘텐츠:🎜🎜이 섹션에서 다루는 구문 콘텐츠는 원하지 않는 한 거의 사용되지 않습니다. 모든 것을 이해하려면 구문을 건너뛰면 됩니다. 🎜
🎜함수 내에서 new.target 속성을 ​​사용하여 new를 사용하여 호출되었는지 확인할 수 있습니다. 🎜🎜일반 호출의 경우 비어 있습니다. new를 사용하는 호출의 경우 함수와 같습니다. 🎜
let accumulator = new Accumulator(1); // 初始值 1accumulator.read(); // 添加用户输入的 valueaccumulator.read(); // 添加用户输入的 valuealert(accumulator.value); // 显示这些值的总和复制代码
🎜함수 내부에서 를 통해 함수가 전달되는지 확인하는 데 사용할 수 있습니다. new 에 의해 호출되는 "생성자 모드"는 여전히 new에 의해 호출되지 않는 "일반 모드"입니다. 🎜🎜다음과 같이 new 호출이 일반 호출과 동일한 작업을 수행하도록 할 수도 있습니다. 🎜rrreee🎜이 접근 방식은 구문을 더 유연하게 만들기 위해 라이브러리에서 때때로 사용됩니다. 이렇게 하면 사람들이 함수를 호출할 때 new 사용 여부에 관계없이 프로그램이 작동합니다. 🎜🎜어디서나 사용하는 것은 좋지 않습니다. 왜냐하면 new를 생략하면 코드에서 무슨 일이 일어나고 있는지 관찰하기 어렵기 때문입니다. 그리고 new를 통해 우리는 이것이 새로운 객체를 생성한다는 것을 알 수 있습니다. 🎜

생성자의 return🎜🎜일반적으로 생성자에는 return 문이 없습니다. 이들의 임무는 this에 필요한 모든 항목을 작성하고 자동으로 결과로 변환하는 것입니다. 🎜🎜그러나 return 문이 있는 경우 규칙은 간단합니다. 🎜
  • return이 개체를 반환하면 대신 이 개체를 반환합니다. 이것.
  • return이 기본 유형을 반환하는 경우 무시합니다.
🎜즉, 개체가 포함된 return은 해당 개체를 반환하고, 다른 모든 경우에는 this가 반환됩니다. 🎜🎜예를 들어, 여기서 return은 객체를 반환하여 this를 재정의합니다. 🎜rrreee🎜다음은 return이 비어 있는 예입니다(또는 다음과 같이 할 수 있습니다). 효과가 없는 기본 유형 추가): 🎜rrreee🎜보통 생성자에는 return 문이 없습니다. 여기서는 주로 완전성을 위해 반환된 개체의 특별한 동작을 언급합니다. 🎜

괄호 생략

🎜 그런데 매개변수가 없으면 new 뒤의 괄호를 생략할 수 있습니다. 🎜rrreee🎜아니요 여기서는 괄호를 생략해야 합니다. "좋은 스타일"로 간주되지만 사양에서 구문을 허용합니다. 🎜🎜생성자의 메서드🎜🎜생성자를 사용하여 객체를 생성하면 많은 유연성이 제공됩니다. 생성자에는 객체가 생성되는 방식과 객체에 무엇을 넣을지 정의하는 매개변수가 있을 수 있습니다. 🎜

当然,我们不仅可以将属性添加到 this 中,还可以添加方法。

例如,下面的 new User(name) 用给定的 name 和方法 sayHi 创建了一个对象:

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() { ... }
}
*/复制代码

类 是用于创建复杂对象的一个更高级的语法,我们稍后会讲到。

总结

  • 构造函数,或简称构造器,就是常规函数,但大家对于构造器有个共同的约定,就是其命名首字母要大写。
  • 构造函数只能使用 new 来调用。这样的调用意味着在开始时创建了空的 this,并在最后返回填充了值的 this

我们可以使用构造函数来创建多个类似的对象。

JavaScript 为许多内置的对象提供了构造函数:比如日期 Date、集合 Set 以及其他我们计划学习的内容。

对象,我们还会回来哒!

在本章中,我们只介绍了关于对象和构造器的基础知识。它们对于我们在下一章中,学习更多关于数据类型和函数的相关知识非常重要。

在我们学习了那些之后,我们将回到对象,在 info:prototypes 和 info:classes 章节中深入介绍它们。

作业题

先自己做题目再看答案。

1. 两个函数 — 一个对象

重要程度:⭐️⭐️

是否可以创建像 new A()==new B() 这样的函数 AB

function A() { ... }function B() { ... }let a = new A;let b = new B;

alert( a == b ); // true复制代码

如果可以,请提供一个它们的代码示例。

2. 创建 new Calculator

重要程度:⭐️⭐️⭐️⭐️⭐️

创建一个构造函数 Calculator,它创建的对象中有三个方法:

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

例如:

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

alert( "Sum=" + calculator.sum() );
alert( "Mul=" + calculator.mul() );复制代码

3. 创建 new Accumulator

重要程度:⭐️⭐️⭐️⭐️⭐️

创建一个构造函数 Accumulator(startingValue)

它创建的对象应该:

  • 将“当前 value”存储在属性 value 中。起始值被设置到构造器 startingValue 的参数。
  • read() 方法应该使用 prompt 来读取一个新的数字,并将其添加到 value 中。

换句话说,value 属性是所有用户输入值与初始值 startingValue 的总和。

下面是示例代码:

let accumulator = new Accumulator(1); // 初始值 1accumulator.read(); // 添加用户输入的 valueaccumulator.read(); // 添加用户输入的 valuealert(accumulator.value); // 显示这些值的总和复制代码

相关免费学习推荐:JavaScript(视频)

위 내용은 JavaScript 생성자와 "new" 연산자에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.im에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제