js는 Object 생성자 함수 이외에도 String,Number,Boolean,Function, Array, Date, RegExp, Promise등의 빌트인 생성자 함수를 지원한다.
사용법 : const person = new Object();
똑같은 여러 객체를 만들경우 코드가 중복되며 비효율적이다.
const circle1 = {
radius:5,
getDiameter(){
return 2 * this.radius
}
}
const circle2 = {
radius:10,
getDiameter(){
return 2 * this.radius
}
}
function Circle(radius) {
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
}
const circle1 = new Circle(5);
const circle2 = new Circle(10);
// 프로퍼티구조가 동일한 객체를 여러 개 생성할 경우 편리하다.
this는 객체 자신의 프로퍼티나 메서드를 참조하기 위한 자기 참조 변수이다.
함수 호출 방식 | this가 가리키는 값(바인딩) |
---|---|
일반 함수로 호출 | 전역객체 |
메서드로서 호출 | 메서드를 호출한 객체 |
생성자 함수로서 호출 | 생성자 함수가 생성할 인스턴스 |
암묵적으로 빈 객체(생성자 함수가 생성한 인스턴스)가 생성되고 this에 바인딩된다.
이 처리는 런타임 이전에 실행된다.
바인딩
바인딩이란 식별자와 값을 연결하는 과정을 의미한다. 예를 들어, 변수 선언은 변수 이름과 확보된 메모리 공간의 주소를 바인딩 하는 것이다. this 바인딩은 this와 this가 가르킬 객체를 바인딩하는 것이다.function Circle(radius){ console.log(this); // Circle () ... }
2. 인스턴스 초기화
생성자 함수에 기술되어 있는 코드가 한 줄씩 실행되어 this에 바인딩되어 있는 인스턴스를 초기화한다.즉,
this에 바인딩되어 있는 인스턴스에 프로퍼티나 메서드를 추가하고 생성자 함수가 인수로 전달받은 초기값을 인스턴스 프로퍼티에 할당하여 초기화하거나 고정값을 할당한다.
function Circle(radius) {
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
return this; // 1.암묵적으로 this 가 리턴된다
return {}; // 2.객체를 반환하는 경우 암묵적 this반환이 무시된다
return 100; // 3.원시값을 반환할 경우 무시되고 this가 반환된다.
}
console.log(new Circle(5));
// 1. Circle { radius: 5, getDiameter: [Function (anonymous)] }
// 2. {}
// 3. Circle { radius: 5, getDiameter: [Function (anonymous)] }
js의 경우 함수 또한 객체로 인식되어 프로퍼티 소유, 메서드 또한 소유할 수 있다.
일반 객체와 다른 점은 호출이 가능하다는 것이다.
function foo() {}
// 일반적인 함수로서 호출 : [[Call]]이 호출된다
foo()
// 생성자 함수로서 호출 : [[Construct]]이 호출된다
new foo();
내부 메서드[[Call]]을 갖는 함수 객체 = callable
내부 메서드[[Construct]]를 갖는 함수 객체 = constructor
내부 메서드[[Construct]]를 갖지않는 함수 객체 = non-constructor
함수 객체의 경우 반드시 callable 이여야 한다.
constructor : 함수 선언문, 함수 표현식 , 클래스
non-constructor : 메서드(ES6 메서드 축약 표현), 화살표 함수
// constructor
function foo(){}
const bar = function () {};
const baz = {
x:function () {}
};
// non-constructor
const arrow = () => {}
const person = {
name:"Lee",
getName(){
return this.name
}
}
new arrow() // TypeError
new person.getName() // TypeError
new 연산자의 경우 [[Construct]] 가 호출되기에 constructor 이여야 한다.
new 없이 함수를 호출할경우 [[Call]]이 호출된다. 생성자 함수가 new 연산자 없이 호출되는 것을 방지하기 위해 파스칼 케이스 컨벤션을 이용하나 실수는 언제든 발생할 수 있다. 이러한 위험성을 피하기 위해 new.target을 지원한다.(ES6)
function Circle(radius) {
if(!new.target){ // 함수가 new 연산자와 함께 호출되지 않으면 new.target은 undefined을 반환한다.
return new Circle(radius);
}
...
}
const circle = Circle(5); == new Circle(5)
다음 조건을 만족하는 객체를 일급 객체라 한다
1. 무명의 리터럴로 생성 가능하다. 즉 런타임에 생성이 가능하다
2. 변수나 자료구조에 저장할 수 있다.
3. 함수의 매개변수에 전달할 수 있다.
4. 함수의 반환값으로 사용할 수 있다.
function square(number) {
return number * number;
}
console.dir(Object.getOwnPropertyDescriptors(square));
{
length: { value: 1, writable: false, enumerable: false, configurable: true },
name: { value: 'square', writable: false, enumerable: false, configurable: true },
arguments: { value: null, writable: false, enumerable: false, configurable: false },
caller: { value: null, writable: false, enumerable: false, configurable: false },
prototype: { value: {}, writable: true, enumerable: false, configurable: false }
}
arguments,caller,length,name,prototype 프로퍼티는 모두 함수 객체의 데이터 프로퍼티이다.
이들 프로퍼티는 일반 객체에는 없는 함수 객체 고유의 프로퍼티다.
__proto__
의 경우 접근자 프로퍼티 이며 함수 객체 고유의 프로퍼티가 아닌 Object.prototype 객체의 프로퍼티를 상속 받은 것이다.
함수 객체의 argument 프로퍼티 값은 argument 객체이다.
argument객체는 함수 호출 시 전달된 인수들의 정보를 담고 순회가능한 유사 배열 객체이며, 함수 내부에서 지역 변수처럼 사용된다.
function sum() {
let res = 0;
for (const item of arguments) {
// arguments 객체는 매개변수 개수를 확정할 수 없는 가변 인자 함수를 구현할 때 유용하다.
res += item;
}
return res;
}
console.log(sum());
console.log(sum(1));
console.log(sum(1, 2));
console.log(sum(1, 2, 3));
// 0
// 1
// 3
// 6
함수를 정의할 때 선언한 매개변수의 개수를 가리킨다.
ES6 이전에는 빈 문자열의 값을 반환한다
ES6 부터는 함수 이름을 반환한다.
var namedFunc = function foo() {};
console.log(namedFunc.name);
var namedFunc1 = function () {};
console.log(namedFunc1.name);
function bar() {}
console.log(bar.name);
// foo
// namedFunc1
// bar
생성자 함수로 호출할 수 있는 객체,즉 constructor만이 소유하는 프로퍼티이다.