>웹 프론트엔드 >JS 튜토리얼 >JavaScript의 팩토리 함수 및 생성자에 대한 간략한 토론

JavaScript의 팩토리 함수 및 생성자에 대한 간략한 토론

青灯夜游
青灯夜游앞으로
2020-11-30 18:05:494219검색

JavaScript의 팩토리 함수 및 생성자에 대한 간략한 토론

JavaScript 언어는 다른 프로그래밍 언어와 비교하여 혼란스러운 내용을 들을 수 있으며 그 중 하나는 팩토리 함수 및 생성자입니다.

팩토리 함수

소위 팩토리 함수는 이러한 내장 함수를 호출하면 실제로 클래스 인스턴스가 생성된다는 의미입니다." , 실제로 클래스를 사용하여 객체를 만든 다음 객체를 반환합니다. Javascript 자체는 엄격한 객체 지향 언어가 아니기 때문에(클래스를 포함하지 않음) 실제로 Javascript에는 엄격한 "팩토리 기능"이 없습니다. , 그러나 Javascript에서는 함수를 사용하여 클래스를 시뮬레이션할 수 있습니다. 다음 예를 살펴보겠습니다.

function person(firstName, lastName, age) {
  const person = {};
  person.firstName = firstName;
  person.lastName = lastName;
  person.age = age;
  return person;
}

위 코드는 새 객체를 생성하고 전달된 매개변수를 객체에 속성으로 첨부하고 새 객체를 반환합니다.

사실 팩토리 함수도 이해하기 쉽습니다.

  • 함수입니다.

  • 객체를 생성하는 데 사용됩니다.

  • 공장과 같습니다. "생성"하는 기능은 모두 "표준 부분"(동일한 속성을 가짐)

Constructor

다른 주류 프로그래밍 언어와 달리 JavaScript의 생성자는 일반적인 클래스의 특정 메서드로 존재하지 않습니다. 함수가 사용됩니다 객체의 클래스가 생성되면 이를 생성자 또는 생성자라고 합니다. 함수가 진정한 생성자가 되려면 다음 조건을 충족해야 합니다.

  • 새 객체의 속성(this) 설정하려면 일반적으로 속성과 메서드를 추가합니다.

  • 생성자는 반환 문을 포함할 수 있지만(권장되지 않음) 반환 값은 this 또는 다른 비객체 유형 값이어야 합니다

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

new 키워드를 사용하세요.

위에서 언급한 것처럼 new를 사용하여 클래스나 개체를 만들면 다음과 같은 질문이 생길 수 있습니다. new 来类或者对象,那么你可能会有以下几个问题:

  1. 我们可以在工厂函数中使用 new 关键字吗?
  2. 如果我们在工厂和构造函数中使用new关键字会发生什么
  3. 如果在使用构造函数创建对象实例时不使用new关键字会发生什么

好的,试着找出以上问题的答案之前,我们先做一个小练习来理解这里面发生了什么。

使用new关键字同时使用工厂和构造函数创建两个对象,接着在控制台打印这两个对象。

使用工厂函数

function person(firstName, lastName, age){
  const person = {}
  person.firstName = firstName;
  person.lastName = lastName;
  person.age = age;
  return person;
}

const mike = new person('mike', 'grand', 23);

JavaScript의 팩토리 함수 및 생성자에 대한 간략한 토론

正如我们在上述所看到的,这里的__proto__ 指向其原型对象的指针,让我们试着找出原型对象是什么。为了找出上面mike对象的指向原型对象,让我们做简单的===等式检查。

JavaScript의 팩토리 함수 및 생성자에 대한 간략한 토론

嗯,有趣的是,它指向 Object.prototype。好的,让我们用构造函数做同样的实验。

理解 JavaScript 的原型

理解原型之前,需要记住以下几点知识:

  • 所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(null除外)
  • 所有的引用类型(数组、对象、函数),都有一个__proto__属性,属性值是一个普通的对象
  • 所有的函数,都有一个prototype属性,属性值也是一个普通的对象
  • 所有的引用类型(数组、对象、函数),__proto__属性值指向它的构造函数的prototype属性值

通过代码解释一下:

// 要点一:自由扩展属性
var obj = {}; obj.a = 100;
var arr = []; arr.a = 100;
function fn () {}
fn.a = 100;

// 要点二:__proto__
console.log(obj.__proto__);
console.log(arr.__proto__);
console.log(fn.__proto__);

// 要点三:函数有 prototype
console.log(fn.prototype)

// 要点四:引用类型的 __proto__ 属性值指向它的构造函数的 prototype 属性值
console.log(obj.__proto__ === Object.prototype)

使用构造函数

注意:在JavaScript中,这些构造函数也被称为 constructor,因为它们用于创建对象。
function Person(firstName, lastName, age) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.age = age;
}
const mike = new Person('mike', 'grand', 23);

JavaScript의 팩토리 함수 및 생성자에 대한 간략한 토론

当我们展开第一层的的__proto__时,它内部还有另一个__proto__

    팩토리에서 new 키워드

    JavaScript의 팩토리 함수 및 생성자에 대한 간략한 토론팩토리와 생성자에서 new 키워드를 사용하면 어떻게 되나요?

    생성자를 사용하여 객체 인스턴스를 생성할 때 새 키를 사용하지 않으면 어떻게 되나요? 단어

좋아요, 위 질문에 대한 답을 찾기 전에 여기서 무슨 일이 일어나고 있는지 이해하기 위해 약간의 연습을 해보겠습니다. JavaScript의 팩토리 함수 및 생성자에 대한 간략한 토론

new 키워드를 사용하여 두 개의 개체를 만듭니다. 팩토리와 생성자를 동시에 실행한 다음 콘솔에 두 개체를 인쇄합니다. 🎜

🎜팩토리 함수 사용🎜

function Person(firstName, lastName, age) {
    // this = {};
    // this.__proto__ = Person.prototype;

    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
    
    // return this;
}
🎜JavaScript의 팩토리 함수 및 생성자에 대한 간략한 토론🎜🎜위에서 볼 수 있듯이 여기 __proto__ code>에 대한 포인터가 있습니다. 프로토타입 객체, 프로토타입 객체가 무엇인지 알아보도록 하겠습니다. 위의 <code>mike 개체가 가리키는 프로토타입 개체를 찾으려면 간단한 === 동일성 검사를 수행해 보겠습니다. 🎜🎜JavaScript의 팩토리 함수 및 생성자에 대한 간략한 토론🎜🎜흠흠 , 흥미롭게도 Object.prototype을 가리킵니다. 좋습니다. 생성자를 사용하여 동일한 실험을 해보겠습니다. 🎜🎜🎜JavaScript의 프로토타입을 이해하세요🎜🎜🎜프로토타입을 이해하기 전에 다음 지식을 기억해야 합니다. 🎜
    🎜모든 참조 유형(배열, 객체, 함수)에는 객체 특성이 있으며 속성( null 제외)🎜🎜모든 참조 유형(배열, 객체, 함수)에는 __proto__ 속성이 있고 속성 값은 일반 객체입니다.🎜🎜모든 함수에는 프로토타입 속성이 있으며 속성 값도 일반 객체입니다.🎜🎜모두 참조 유형(배열, 객체, 함수)에서 __proto__ 속성 ​​값은 생성자의 프로토타입 속성 값을 가리킵니다🎜🎜🎜코드를 통해 설명하세요:🎜
function person(firstName, lastName, age) {
    // this = {};
    // this.__proto__ = Person.prototype; 
 
  
    const person = {};
    person.firstName = firstName;
    person.lastName = lastName;
    person.age = age;
    return person;
    
    // return this;
}

🎜생성자 사용🎜

참고 : JavaScript에서 이러한 생성자는 객체를 생성하는 데 사용되므로 🎜constructor🎜라고도 합니다.
function Person(firstName, lastName, age) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.age = age;
}
const mike = new Person(&#39;mike&#39;, &#39;grand&#39;, 23);
const bob = Person(&#39;bob&#39;, &#39;grand&#39;, 23);
🎜JavaScript의 팩토리 함수 및 생성자에 대한 간략한 토론🎜🎜첫 번째 레이어의 __proto__를 확장하면 그 안에 또 다른 __proto__가 있으므로 다시 확장합니다. 🎜🎜🎜🎜🎜이제 프로토타입 객체가 위와 같은지 확인해 보겠습니다. 🎜🎜🎜🎜

他们是不同的。 当我们使用工厂函数创建对象时,它的__proto__指向Object.prototype,而当从构造函数创建对象时,它指向它的构造函数原型对象。 那么这里发生了什么?

new 背后所做的事

当我们在创建对象时使用带有构造函数的new关键字时,new 背后所做的事不多。

new 运算符创建一个用户自定义的对象类型的实例或具有构造函数的内置对象的实例。 new 关键字会进行如下操作:

  1. 创建一个空的简单 JavaScript 对象 (即 {})
  2. 链接该对象(即设置该对象的构造函数)到另一个对象
  3. 将步骤1新创建的对象作为 this 的上下文
  4. 如果该函数没有返回对象,则返回 this

注释行是伪代码,表示在 new 关键字,JS 背后帮我们做的事情。

function Person(firstName, lastName, age) {
    // this = {};
    // this.__proto__ = Person.prototype;

    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
    
    // return this;
}

另外,让我们看看如果将上面的隐式代码添加到工厂函数中会发生什么。

function person(firstName, lastName, age) {
    // this = {};
    // this.__proto__ = Person.prototype; 
 
  
    const person = {};
    person.firstName = firstName;
    person.lastName = lastName;
    person.age = age;
    return person;
    
    // return this;
}

即使使用new关键字调用时将隐式代码添加到工厂函数中,也不会对结果产生任何影响。这是因为,由于我们没有在函数中使用 this 关键字,而且我们显式地返回了一个除this之外的自定义对象,因此没有必要使用隐式代码。无论我们是否对工厂函数使用new关键字,对输出都没有影响。

如果忘记了 new 关键字怎么办

JavaScript 中有许多概念,有时难以掌握。 new 操作符就是其中之一。 如果你不能正确理解它,那么在运行 JavaScript 应用程序时会产生令人讨厌的后果。 在像 Java这 样的语言中,严格限制了如何使用 new 关键字。 但是在 javascript 中,并不是那么严格,如果你不能正确理解它们可能会导致很多问题。

在 JavaScript 中:

  • 可以对任何函数使用 new 运算符
  • 可以使用或不使用 new 关键字将函数作为构造函数调用

让我们看看上面的例子,使用和不使用 new 关键情况

function Person(firstName, lastName, age) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.age = age;
}
const mike = new Person(&#39;mike&#39;, &#39;grand&#39;, 23);
const bob = Person(&#39;bob&#39;, &#39;grand&#39;, 23);

然后,如果查看创建的对象实例,你希望看到什么?

JavaScript의 팩토리 함수 및 생성자에 대한 간략한 토론

发生了什么? 使用 new 运算符,正如我们所期待的一样输出正确的对象,但没有new运算符,结果是undefined 怎么可能呢?

如果你对 JavaScript 作用域 this 关键字的工作原理有所了解,那么你可以猜到这里发生了什么? 让我们来看看。

JavaScript의 팩토리 함수 및 생성자에 대한 간략한 토론

看起来我们传递给没有new关键字的函数的所有属性都已设置为window对象。 那是因为到那个时候函数内部的这个变量引用了globalwindow 对象,基本上我们在这里做的就是污染了全局对象。

这是你可以对你的JavaScript程序做的非常讨厌的事情。 因此,使用new运算符,JavaScript引擎将this 变量设置为引用新创建的对象实例,这就是为什么我们可以看到传递给构造函数的所有属性都已设置为 mike

但是在没有new运算符的情况下调用构造函数的情况下,JavaScript 引擎会将 this 解释为常规函数调用,而没有显式返回语句时返回undefined。 这就是理解new 运算符在JavaScript中的工作原理非常关键的原因。

原文地址:https://medium.com/@chamikakasun/javascript-factory-functions-vs-constructor-functions-585919818afe

更多编程相关知识,请访问:编程入门!!

위 내용은 JavaScript의 팩토리 함수 및 생성자에 대한 간략한 토론의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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