#1
let ob = {};
객체를 리터럴로 생성하는 방법이다. 빈 객체를 리터럴로 생성하기 위해서는 중괄호 {}
를 변수에 할당하면 된다.
하지만 객체의 중괄호는 코드 블록을 의미하지 않는다.
코드 블록문은 문의 종료를 의미하는 자체 종결성을 가지고 있어서
예를 들면 함수의 중괄호나 제어문의 중괄호 같은 경우, 끝에 세미콜론 ;
을 붙이지 않는다.
따라서 객체에는 마지막에 세미콜론 ;
을 붙여준다.
객체 리터럴로 객체를 생성하는 것은 뭔가 보기에도 직관적이고 편해보이지만, 하나의 객체만 생성하기 때문에 value
가 다른 여러 객체를 생성해야 하는 경우에는 비효율적이다.
100명의 신원 정보를 나타대기 위해서는 100개의 객체 리터럴을 생성해야 하기 때문이다.
따라서 이런 부분은 생성자 함수를 통해 효율적으로 구현할 수 있다.
#2
function User(name) {
this.name = name;
this.getNameLength = function () {
return this.name.length;
}
}
let user1 = new User('muzi');
let user2 = new User('frodo');
console.log(user1.getNameLength()) // 4
console.log(user2.getNameLength()) // 5
생성자 함수를 사용하는 경우에는 해당 함수의 이름 첫 글자를 대문자로 기입한다. 이런 규칙이 필요조건은 아니지만, 이 함수가 생성자 함수임을 구분하기 위한 관례라고 한다.
여기서 중요하게 봐야 할 것은 this
키워드와 new
키워드이다.
먼저 name
앞에 this
키워드가 붙어있는데, 꼴을 보면 임의의 객체를 의미하는 것 처럼 보인다.
#3
let thiss = {
name: 'muzi'
};
console.log(thiss) // {name: 'muzi'}
console.log(thiss.name) // muzi
위 코드와 같이 thiss
라는 이름의 객체를 선언했다고 가정해보았다.
여기서 우리가 muzi
를 출력하려면 thiss.name
꼴의 리터럴로 접근해야 한다.
다시 돌아와서
자바스크립트에는 전역에서 window
( global )로 이미 정의된 전역 객체가 있고, this
가 해당 전역 객체를 바인딩하고 있다. 따라서 window
가 this
의 default값이다.
하지만 window
로 안쓰고 this
라고 쓰는 이유는 this
가 어느 객체든지 동적으로 바인딩 할 수도 있기 때문이다.( -> 내생각 )
나중에 더 자세히 작성할 내용이지만, 일반 함수 내부에서 this
를 선언하면 함수의 호출 방법에 따라서 this
가 가리키는 객체가 동적으로 결정된다.
#4
function User(name) {
this.name = name;
this.getNameLength = function () {
return this.name.length;
}
console.log(this) // User {name: 'muzi', getNameLength: ƒ}
}
let user1 = new User('muzi');
//let user2 = new User('frodo');
//console.log(user1.getNameLength())
//console.log(user2.getNameLength())
#2
번 코드를 그대로 가져와, User
함수 안에서 this
를 콘솔로 찍어보니까 User
객체가 출력되었다.
이는 User
함수 안의 this
가 User
라는 객체를 바인딩하고 있다는 뜻이다.
그러면 객체는 언제 생성한걸까?
let user1 = new User('muzi');
이 구문이 바로 User
객체 생성의 근원이다.
new
키워드와 함께 함수를 호출하면, 함수의 내부에서 this
로 선언한 프러퍼티들을 그대로 가져와 객체를 반환한다.
이렇게 생성된 객체를 인스턴스라고 부른다.
따라서 우리가 인스턴스를 생성하기 위해서 해야하는 일을 요약하면 아래와 같다.
- 함수 이름 첫 글자 대문자로 적어
- 함수 내부에 this.~ 로 미래의 프러퍼티 정의 ( ~ 는 인스턴스의 프로퍼티가 될 예정 )
- 이렇게 만든 함수를 new키워드와 함께 호출
- 이걸 변수에 할당시켜서 구조가 동일한 객체 여러 개를 생성 할 수 있음
#5
function User() {
//this.name = name;
//this.getNameLength = function () {
// return this.name.length;
//}
console.log(this) // window {...}
}
//let user1 = new User('muzi');
//let user2 = new User('frodo');
//console.log(user1.getNameLength())
//console.log(user2.getNameLength())
User()
만약에 위의 코드 처럼 User
함수를 생성자 함수로 만들지 않고 그냥 호출한다면, this
는 window
객체를 가리킨다.
함수는 객체라서, 일반 객체가 가지고 있는 내부 슬롯이나 메서드들을 가지고 있다.
하지만 함수는 일반 객체와는 다르다. 일반 객체는 호출할 수 없지만, 함수는 호출할 수 있기 때문이다. 따라서 함수는 객체 메서드에 이어 [[Call]]
과 [[Constructor]]
메서드를 추가로 가지고 있다.
함수가 일반 함수로 호출되면 [[Call]]
이 호출되고, 생성자 함수로 호출되면 [[Constructor]]
가 호출된다.
따라서 생성자 함수는 함수 선언언문이나 표현식으로도 만들 수 있기 때문에 모든 함수는 [[Call]]
이 호출 될 수 있다.
반면 new
키워드와 함께 호출할 수 없는 함수 형태인 메서드와 화살표 함수는 생성자 함수로 호출할 수 없기 때문에 [[Constructor]]
를 가지지 않는다. 이런 함수 객체를 non-constructor
라고 부른다.
Call : 모든 함수
Constructor : 함수 선언문, 함수 표현식, 클래스( 클래스도 함수다 )
non-constructor : 메서드, 화살표 함수