중괄호({}
)를 사용하여 객체를 생성한다.
// 프로퍼티가 추가된 객체 생성
var obj = {
name: "kim",
getName: function () {
console.log(this.name);
}
};
// 빈 객체 생성
var obj = {};
new
연산자를 붙여서 실행한다.function Person(name) {
this.name = name;
this.showName = function () {
console.log(`My name is ${this.name}`);
};
}
var person = new Person("Son");
person.showName();
객체 리터럴을 사용하는 방식도 내부적으로는 생성자 함수와 new
연산자를 사용하는 방식으로 실행된다.
(빌트인(Built-in) 함수인 Object
생성자 함수를 사용한다.)
var obj = {};
// 위의 코드는 내부적으로 아래의 방식으로 실행된다.
var obj = new Object();
객체를 생성하는데 사용하는 함수
생성자 함수는 객체를 생성하는데 사용하는 함수로 new
연산자와 호출할 경우 객체를 생성할 수 있다.
new
연산자 : 사용자 정의 객체 타입 또는 내장 객체 타입의 인스턴스를 생성하는 연산자
아래와 같이 사용할 수 있다.
function Cons(name, age) {
this.name = name;
this.age = age;
}
var obj = new Cons("Lee", "21");
/*
obj = {
name: "Lee",
age: 21
}
이런 형태의 객체가 생성된다.
*/
생성자 함수는 함수 정의차원이 아니라 그냥 용도에 따라 구분한 개념이므로 일반 함수처럼 호출해도 에러는 발생하지 않는다.
var obj = Cons("Lee", "21"); // undefined
다만 이 경우 Cons()
함수 내부의 this
는 전역객체를 가리키고 있으므로, 전역객체에 name
과 age
프로퍼티가 추가된다.
new
연산자 강제하기new.target
속성(property)을 통해 함수 또는 생성자가 new
연산자를 사용하여 호출됐는지를 감지할 수 있다.
new
연산자로 인스턴스화된 생성자 및 함수에서, new.target
은 생성자 또는 함수 참조를 반환하고, 일반 함수 호출에서는 undefined
를 반환한다.
function Foo() {
if (!new.target) { throw 'Foo() must be called with new'; }
}
try {
Foo();
} catch (e) {
console.log(e);
// expected output: "Foo() must be called with new"
}
new 연산자는 빈 객체 생성과 함수 호출, 객체 반환을 일으킨다.
new Cons("Lee", 21)
을 사용해서 함수를 실행하면 아래와 같은 알고리즘이 동작한다.
1. 빈 객체를 생성하고 this
가 빈 객체를 가리키게 한다.
2. 함수를 실행한다.
3. this
를 반환한다.
function Cons(name) {
// 빈 객체가 생성되고 this에 저장
this = {};
// 함수 실행
// this는 객체({})기 때문에 this.name = name 구문은 객체에 name 값을 넣는 것과 같다.
this.name = name;
this.age = age;
return this;
}
이 설명 보다는 apply
나 call
함수를 이용해 설명하는게 좀 더 직관적이고 실제 작동원리에도 더 가까울 것이다.
var temp = {};
// apply를 통해 Cons의 this값을 temp로 변경하여 함수를 실행한다.
var obj = Cons.apply(temp);
생성자 함수에는 기본적으로 return
문이 존재하지 않지만 위에서 말한대로 new
연산자가 함수반환을 일으키기때문에 obj
라는 변수에 생성된 객체가 들어가게된다.
function plus(num1, num2){
var num = num1 + num2;
return num;
}
var variable = new plus(1, 2);
console.log(variable); // {}
이 코드의 동작을 살펴보자
먼저 빈 객체를 생성하고, 함수를 호출해서 함수 내부 this
에 방금 생성한 빈 객체를 대입할 것이다.
그런데 plus 함수에는 this가 없다. 그래서 빈 객체에는 아무런 속성이 추가되지않고 빈 객체가 반환되게 될 것이다.
빈 객체가 반환된다는 것은 return num;
이 부분을 무시하고 빈 객체를 반환하는 return
문이 실행됐다는 것이다.
이처럼 기본타입을 반환하는 함수는 new
연산자를 사용했을 때 new
연산자로 생성된 객체를 반환하도록 하는 반면, 객체를 반환하는 함수는 return문을 무시하지 못한다.
예를 들어 아래 코드에서는 생성자 함수는 return문에 명시된 객체를 반환할 것이다.
function plus(num1, num2) {
var num = num1 + num2;
this.result = num;
plusObj = this;
return {
name: "Lee",
age: 21
}
}
var obj = new plus(1, 2); // 생성자 함수의 return문에 명시된 객체 반환
console.log(plusObj.result); // 3
이 때 plubObj
는 함수의 런타임에 전역변수로 선언되며 new
연산자로 생성한 객체를 저장하게된다.
return
은 객체 리터럴을 반환하고 있기 때문에 obj
는 new
연산자가 생성한 객체를 저장하지않는다.
하지만 전역으로 정의된 plusObj
는 new
연산자가 실행되면서 생성된 객체를 담고 있기 때문에 다른 객체를 리턴하더라도 new
로 인해 생성된 객체는 분명히 존재한다는것을 확인할 수 있다.
객체를 재사용하기 위함으로, 리터럴 객체를 만드는 방법보다 수고를 덜 수 있다.
var person1 = new Cons("Lee",21);
var person2 = new Cons("Park",2);
var person3 = new Cons("Kim",29);
Reference
https://bamdule.tistory.com/196
https://multifrontgarden.tistory.com/69