들어가며
생성자와 this
에 대해서 알아보았다.
개인적으로 생성자 함수라는 말 보다는 함수의 생성자가 맞다고 생각하지만, 생성자라고 작성하면 읽는데 헷갈리는 부분이 있을 것 같아 이해를 위해 생성자 함수라고 적었다.
- 인사이드 자바스크립트 Ch.4.4를 참고하였다.
생성자와 this
예를 들어 이런 코드가 있다고 해보자.
function foo() {
this.name = 'foo';
// ...
}
var bar = new foo();
bar
는 foo
에게 접근할 수 있다.
이것이 가능한 이유는 bar
가 생성될 때 foo()
의 constructor
로 하여금, bar.__proto__
가 foo()의 prototype
객체를 가리키게끔 했기 때문이다.
그리고 이 때 새롭게 생성된 new object
의 this
는 bar
에 바인딩이 된다. 그리고 이러한 바인딩을 new 바인딩 이라고 한다. (여기에 추가적인 설명이 있다)
그런데 만약 new
를 사용하지 않고 객체를 만들면 어떻게 될까?
생성자 함수를 new를 붙이지 않고 호출할 경우
그냥 함수를 실행한 결과와 같다.
function Person(name) {
this.name = name;
}
var qux = Person('qux');
console.log(qux); // undefined
console.log(window.name); // qux
즉 새로 만든 객체에 올바르게 값이 들어가지 않는다. 이런 불상사를 막기 위해 대부분의 라이브러리는 내부적으로 아래와 같은 처리를 해준다고 한다.
new 를 붙이지 않아도 안전한 함수 만들기
function PersonSafe(name) {
if (!(new.target))
return new PersonSafe(name);
this.name = name;
}
var quxSafe = PersonSafe('qux');
console.log(quxSafe); // 결과는 아래에 있다
PersonSafe {name: "qux"}
name: "qux"
__proto__: Object
즉 PersonSafe
안에서 new
의 여부를 체크한 뒤에, 없다면 new
키워드로 재귀적으로 함수를 호출 한다.
그리고 !(new.target)
부분이 책에서는 !(this instanceof arguments.callee)
라고 되어있는데, StackOverflow에서 !(new.target)
가 맞는 표현이라고 하더라. 채택된 답변의 하단에 해당 내용이 있다.
(저 게시물은 내가 올린 질문이었는데 질문 올릴 당시에는 계속 고민하다가 올린건데, 댓글을 보고 바로 이해했다. 내 질문이 바보같았다는것을 ㅎㅎ;;)
생성자 함수가 아무것도 return하지 않을 경우
일반적인 함수의 return
일반적인 함수는 return
값이 명시되어있지 않으면 undefined
를 반환한다.
function printMe(name) {
console.log(name);
}
printMe("snaag"); // snaag
// undefined
그렇다면 생성자 함수는 return
값이 있을 때와 없을 때가 어떻게 다를까?
생성자 함수의 return
따로 return
을 해주지 않았을 경우, this
로 바인딩 된 새로운 객체를 반환한다. (일반적인 반환을 한다)
function Person(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
var qux = new Person('qux', 20, 'man');
console.log(qux.name); // qux
console.log(qux.age); // 20
console.log(qux.gender); // man
return
을 명시해 준 경우, 해당 객체를 return
한다.
function Person(name, age, gender) {
this.age = age;
return {name, gender};
}
var qux = new Person('qux', 20, 'man');
console.log(qux); // {name: "qux", gender: "man"}
console.log(age); // ReferenceError: age is not defined
만약 key
와 value
를 아예 다르게 바꿔도, 결과는 동일하다
function Person(name, age, gender) {
return {'hehe':name, 'hehehe':'hehe'};
}
var qux = new Person('qux', 20, 'man');
console.log(qux); // {hehe: "qux", hehehe: "hehe"}
그러나 함수가 return
하는 값이 객체가 아니라 Boolean
, Number
, String
의 경우에는 이러한 반환 값을 무시하고 this
로 바인딩 된 객체가 반환된다.
정리
new
키워드 없이 생성자 함수를 호출할 경우에는, 함수의 코드가 그냥 실행만 된다. 따라서 이러한 것을 막기 위해 new.target
속성으로 재귀적으로 함수를 만들 수 있다.
생성자 함수가 아무것도 return
하지 않을 때에는 this
로 바인딩 된 새로운 객체를 반환한다. 객체를 return
할 경우에는 해당 객체가 반환되지만, 만약 Boolean
, Number
, String
의 경우에는 이러한 반환 값을 무시하고 this
로 바인딩 된 객체가 반환된다.
'자바스크립트 JavaScript' 카테고리의 다른 글
Object(Instance), Class (2) | 2023.01.22 |
---|---|
Prototype, Inheritance (0) | 2023.01.21 |
This 의 바인딩 (0) | 2023.01.20 |
함수 (0) | 2023.01.19 |
Closure (0) | 2023.01.18 |