💡 아래 내용은 모던 자바스크립트 딥다이브를 공부하며 이해했던 내용을 다루고 있습니다. 혹시 틀렸거나 잘못된 정보가 있다면 알려주세요!
new 연산자와 함께 호출하여 빈 객체(인스턴스)를 생성하는 함수입니다.
let myObject = new Object();
const circle = {
raduis: 5
} // 객체 리터럴로 생성하는 방식
객체 리터럴을 사용한 객체 생성 방식은 매우 편리하고 가장 일반적으로 사용되는 방법이지만, 중복을 처리하기 어려운 점, 캡슐화가 불가능하다는 점, 프로토타입 상속이 복잡해진다는 단점이 있다.
JS에서는 '프로토타입'이라는 메커니즘으로 상속을 구현하는데, 객체 리터럴로 객체를 생성하는 경우, 객체의 프로토타입은 기본적으로 Object.prototype으로 설정됩니다. 따라서 다른 객체의 프로토타입을 상속하려면 추가적인 작업이 필요해지고, 이를 권장하지 않습니다.
생성자 함수로 객체를 만들면, 재사용성, 프로토타입 기반 상속, 캡슐화의 장점이 있습니다.
function Person(name) {
this.name = name; // 재사용성
let age = 0; // 캡슐화
this.getAge = function() { // 캡슐화된 속성에 대한 접근자
return age;
}
this.birthday = function() { // 캡슐화된 속성을 수정하는 메서드
age++;
}
}
Person.prototype.greet = function() { // 프로토타입 기반 상속
console.log(`Hello, my name is ${this.name}`);
}
let person1 = new Person('John');
let person2 = new Person('Sarah');
person1.greet(); // "Hello, my name is John"
person2.greet(); // "Hello, my name is Sarah"
console.log(person1.getAge()); // 0
person1.birthday();
console.log(person1.getAge()); // 1
function Person(name) {
console.log(this); // Person {}
this.name = name;
}
function Person(name) {
// 인스턴스 초기화
this.name = name;
}
function Person(name) {
this.name = name;
// this 반환
}
let john = new Person('John');
console.log(john); // Person { name: 'John' }
[[Call]]
: 함수를 호출할 때 사용하는 내부 메서드입니다. 모든 함수 객체는[[Call]]
내부 메서드를 가지고 있으며, 이 메서드가 있어야 함수로서 호출이 가능합니다. 예를 들어, myFunction()와 같이 함수를 호출하면[[Call]]
내부 메서드가 실행됩니다.
function sayHello() {
console.log('Hello!');
}
// 함수를 호출하면 내부적으로 [[Call]] 메서드가 동작합니다.
sayHello(); // 출력: Hello!
[[Construct]]
: new 연산자와 함께 생성자 함수를 호출할 때 사용하는 내부 메서드입니다. 모든 생성자 함수는[[Construct]]
내부 메서드를 가지고 있으며, 이 메서드가 있어야new
키워드를 사용하여 인스턴스를 생성할 수 있습니다. 예를 들어, new MyConstructor()와 같이 생성자 함수를 호출하면[[Construct]]
내부 메서드가 실행됩니다.
function Person(name, age) {
this.name = name;
this.age = age;
}
// new 키워드를 사용해 생성자 함수를 호출하면 내부적으로 [[Construct]] 메서드가 동작합니다.
var person = new Person('John', 30);
console.log(person.name); // 출력: John
console.log(person.age); // 출력: 30
함수는 생성자(constructor)와 비생성자(non-constructor)로 구분되는데, 함수가
new
키워드를 사용하여 호출될 수 있는지 여부에 따라 결정됩니다.
생성자 함수는
new
키워드를 사용하여 인스턴스를 생성할 수 있는 함수입니다. 이 함수를 호출하면this
바인딩을 통해 새 객체가 생성되고, 이 객체는 함수의 프로토타입을 상속받습니다. 생성자 함수는 일반적으로 첫 글자를 대문자로 작성하여 다른 개발자에게 생성자 함수임을 알립니다.
function Person(name) {
this.name = name;
}
const john = new Person('John'); // 'new' 키워드를 사용하여 생성자 함수 호출
console.log(john.name); // 출력: 'John'
비생성자 함수는
new
키워드와 함께 호출할 수 없습니다. 만약new
키워드와 함께 호출하려고 시도하면, TypeError가 발생합니다. 화살표 함수, 메서드 축약 표현, Object, Function 등의 빌트인 함수는 비생성자 함수의 예시입니다.
const arrowFunc = () => {};
new arrowFunc(); // TypeError: arrowFunc is not a constructor
new
연산자는 객체를 생성하고 초기화하는 데 사용됩니다. 이 연산자는 생성자 함수를 호출하며, 그 과정에서 객체를 생성하고 반환합니다.
, 특정 데이터 구조를 나타내는 클래스나 생성자 함수를 정의하고, 그 구조에 맞는 다수의 객체를 만들어야 하는 경우에
new
연산자를 사용할 수 있습니다.
// 생성자 함수를 정의
function Person(name, age) {
this.name = name;
this.age = age;
}
// new 연산자를 사용해 Person 객체를 생성
var person1 = new Person('John', 30);
var person2 = new Person('Jane', 25);
console.log(person1); // Person { name: 'John', age: 30 }
console.log(person2); // Person { name: 'Jane', age: 25 }
사용자가 정의한 클래스나 라이브러리가 제공하는 클래스를 인스턴스화할 때도 new 연산자가 사용됩니다. 예를 들어, Express.js와 같은 웹 프레임워크에서는 라우터 인스턴스를 만들기 위해 new를 사용합니다.
let express = require('express');
let router = new express.Router();
// 생성자 함수
function Person(name, age) {
this.name = name;
this.age = age;
}
// 클래스
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
클래스는
ES6
에 도입된 문법으로, 기존의 프로토타입 기반 객체 지향 패턴을 좀 더 명확하고 쉽게 사용할 수 있도록 제공된 문법입니다. 반면, 생성자 함수는 그 이전부터 존재하는 객체를 생성하는 방식입니다.
ES6에서 도입된 속성으로, 함수나 생성자가
new
연산자를 통해 호출되었는지 아닌지를 확인할 수 있습니다.new
를 통해 호출된 함수 내부에서new.target
을 사용하면,new
연산자가 앞서 호출한 생성자를 참조합니다. 만약 new를 사용하지 않고 일반 함수처럼 호출했다면, new.target은 undefined를 반환합니다.
function ExampleConstructor() {
if (!new.target) {
console.log('Called without new');
} else {
console.log('Called with new');
}
}
ExampleConstructor(); // 출력: 'Called without new'
new ExampleConstructor(); // 출력: 'Called with new'