생각보다 내가 모르는건 많았다.
function Person(name, gender) {
var married = true; // private
this.name = name; // public
this.gender = gender; // public
this.sayHello = function(){ // public
console.log('Hi! My name is ' + this.name);
};
}
var person = new Person('Lee', 'male'); // 생성자 함수 호출
console.log(person); // Person { name: 'Lee', gender: 'male', sayHello: [Function] }
console.log(person.gender); // 'male'
console.log(person.married); // undefined
this
에 연결(바인딩)되어 있는 프로퍼티와 메소드는 public(외부에서 참조 가능)
한 반면, 일반 변수는 private(외부에서 참조 불가능)
하다.
for-in 문은 객체의 문자열 키(key)
를 순회하기 위한 문법이다.
물론 배열에도 사용가능하지만, 순서가 보장되지 않고 배열 요소들만 순회하는 것이 아니기 때문에 배열을 사용할 경우for-of
반복문을 사용하는 것이 권장된다.
var person = {
'name': 'Lee',
gender: 'male'
};
// prop에 객체의 프로퍼티 이름이 반환된다. 단, 순서는 보장되지 않는다.
for (var prop in person) {
console.log(prop + ': ' + person[prop]);
}
/*
name: Lee
gender: male
*/
var array = ['one', 'two'];
// 배열의 경우 인덱스가 반환된다
for (var index in array) {
console.log(index + ': ' + array[index]);
}
/*
0: one
1: two
*/
Object.assign은 타킷 객체
로 소스 객체의 프로퍼티
를 복사한다.
이때 소스 객체의 프로퍼티와 동일한 프로퍼티를 가진 타켓 객체의 프로퍼티들은 소스 객체의 프로퍼티로 덮어쓰기
된다. 리턴값으로 타킷 객체를 반환한다.
Object.assign(target, ...sources)
아래의 예시를 통해 살펴보자.
// Merge
const o1 = { a: 1 };
const o2 = { b: 2 };
const o3 = { c: 3 };
const merge1 = Object.assign(o1, o2, o3);
console.log(merge1); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }, 타겟 객체(o1)가 변경된다!
하지만 객체 내부에 또 다른 객체가 있을 경우 얕은 복사
가 된다. 즉, 객체 내부의 또 다른 객체가 있을 경우 그 값을 변경하면 기존의 객체와 복사된 객체 모두 변경된다.
const user1 = {
name: 'Lee',
address: {
city: 'Seoul'
}
};
// 새로운 빈 객체에 user1을 copy한다.
const user2 = Object.assign({}, user1);
// user1과 user2는 참조값이 다르다.
console.log(user1 === user2); // false
user2.name = 'Kim';
console.log(user1.name); // Lee
console.log(user2.name); // Kim
// 객체 내부의 객체(Nested Object)는 Shallow copy된다.
console.log(user1.address === user2.address); // true
user1.address.city = 'Busan';
console.log(user1.address.city); // Busan
console.log(user2.address.city); // Busan
Object.freeze()를 사용하여 불변(immutable) 객체로 만들수 있지만, 객체 내부의 객체는 변경가능하다.
const user1 = {
name: 'Lee',
address: {
city: 'Seoul'
}
};
// Object.assign은 완전한 deep copy를 지원하지 않는다.
const user2 = Object.assign({}, user1, {name: 'Kim'});
console.log(user1.name); // Lee
console.log(user2.name); // Kim
Object.freeze(user1);
user1.name = 'Kim'; // 무시된다!
console.log(user1); // { name: 'Lee', address: { city: 'Seoul' } }
console.log(Object.isFrozen(user1)); // true
user1.address.city = 'Busan';
console.log(user1); // { name: 'Lee', address: { city: 'Busan' } }
따라서 내부 객체를 변경 불가능하게 만들려면 Deep freeze를 해야 한다.
function deepFreeze(obj) {
const props = Object.getOwnPropertyNames(obj); // 객체의 모든 프로퍼티를 배열로 반환
props.forEach((name) => {
const prop = obj[name]; // 객체의 프로퍼티를 변수에 저장
/*
객체의 프로퍼티가 객체이고 Null이 아닌 경우 해당 프로퍼티에 deepFreeze를 다시 실행
*/
if(typeof prop === 'object' && prop !== null) {
deepFreeze(prop);
}
});
return Object.freeze(obj); // 객체를 불변으로 설정
}
BOM은 브라우저 탭
또는 브라우저 창
의 모델을 생성한다. 최상위 객체는 window
객체로 현재 브라우저 창 또는 탭을 표현하는 객체이다. 또한 이 객체의 자식 객체 들은 브라우저의 다른 기능들을 표현한다. 이 객체들은 Standard Built-in Objects가 구성된 후에 구성된다.
DOM은 현재 웹페이지
의 모델을 생성한다. 최상위 객체는 document
객체로 전체 문서를 표현한다. 또한 이 객체의 자식 객체들은 문서의 다른 요소들을 표현한다. 이 객체들은 Standard Built-in Objects가 구성된 후에 구성된다.