객체
객체는 중괄호{...}를 이용해 생성.
키(key):값(value) 쌍으로 구성된 프로퍼티(property)를 여러 개 넣을 수 있음.
키 에는 문자형, 값에는 모든 자료형이 허용.
let user = new Object(); // 객체 생성자 문법
let user = {}; // 객체 리터럴 문법
프로퍼티 삭제
let user = {
name: "kim",
age: 9,
"likes birds": true,
};
user.isAdmin = true;
delete user.age;
user.likes birds // error
user["likes birds"];
점 표기법, 대괄호 표기법
let user = {
name: 'kim',
age:1,
};
let key = prompt('사용자 어떤 정보 원해?', "name");
alert(user[key]);
let key2 = "name";
alert(user.key2); // undifined
프로퍼티 나열
let user = {
name: 'kim',
age:1,
};
console.log("age" in user); // true
console.log("blabla" in user); // false
let user = {
name: 'kim',
age: 1,
isAdmin: true,
};
for (let key in user) {
console.log(key);
console.log(user[key]);
}
참조에 의한 객체 복사
객체와 원시 타입의 근본적인 차이 중 하나는 객체는 '참조에 의해(by ference)' 저장되고 복사 된다는 것.
참조에 의한 비교
let a = {};
let b = a;
console.log(a == b);
console.log(a === b);
let a1 = {};
let b2 = {};
console.log(a1 == b2);
객체 복사, 병합과 Object.assign
let user = {
name: 'kim',
age: 1
};
let clone = {};
for (let key in user) {
clone[key] = user[key];
}
let permission1 = {canView: true};
let permission2 = {canEdit: true};
Object.assign(user, permission1, permission2);
let clone2 = Object.assign({}, user);
중첩객체복사
let user = {
name: 'kim',
sizes: {
height: 222,
width: 22
}
};
let clone = Object.assign({}, user);
console.log(user.sizes === clone.sizes);
객체의 '진짜 복사본'을 만들려면 '얕은 복사(shallow copy)'를 가능하게 해주는 Object.assign 이나 '깊은 복사'를 가능하게 해주는 _.cloneDeep(obj)를 사용하면 됩니다. 얕은 복사본은 중첩 객체를 처리하지 못하는 점.
가비지 컬렉션
자바스크립트는 도달 가능성(reachability) 이라는 개념을 사용해 메모리 관리를 수행
'도달 가능한(reachable)' 값은 쉽게 말해 어떻게든 접근하거나 사용할 수 있는 값을 의미. 도달 가능한 값은 메모리에서 삭제되지 않음.
내부 알고리즘('mark-and-sweep')
- 가비지 컬렉터는 루트(root) 정보를 수집하고 이를 'mark(기억)' 합니다.
- 루트가 참조하고 있는 모든 객체를 방문하고 이것을 'mark' 합니다.
- mark된 모든 객체에 방문하고 그 객체들이 참조하는 객체로 mark 합니다. 한번 방문한 객체는 전부 mark 하기 때문에 같은 객체를 다시 방문하는 일은 없습니다.
- 루트에 도달 가능한 모든 객체를 방문할 때까지 위 과정을 반복합니다.
- mark 되지 않은 모든 객체를 메모리에서 삭제합니다.
메서드와 'this'
자바스크립트에서 this는 런타임에서 결정됩니다. 메서드가 어디서 정의되었는지 상관없이 this는 '점 앞의 객체가 무엇인가에 따라' 자유롭게 결정됩니다.
객체 리터럴 안에 메서드를 선언할 때 function 생략해도 메서드 정의 가능.
let user = {
sayHi: function() {
alert('hi');
}
};
let user2 = {
sayHi() {
alert('hi');
}
};
자바스크립트의 this는 런타임에서 결정.
let user = {name: 'user'};
let admin = {name: 'admin'};
function sayhi () {
alert(this.name);
}
user.f = sayhi; // user
admin.f= sayhi; // admin
엄격 모드가 아닐 때는 [object window], 엄격 모드일 경우 undefined
function sayHi () {
alert(this);
}
별개의 this가 만들어지는 건 원하지 않고, 외부 컨텍스트에 있는 this를 이용하고 싶은 경우 화살표 함수가 유용합니다. ................ ???? //todo
let user = {
firstName: "보라",
sayHi() {
let arrow = () => alert(this.firstName);
arrow();
}
};
문제 // todo
function makeUser() {
return {
name: "John",
ref: this
};
};
let user = makeUser();
alert( user.ref.name );
'new' 연산자와 생성자 함수
생성자 함수
- 함수 이름의 첫 글자는 대문자로 시작
- 반드시 "new" 연산자를 붙여서 실행
function User(name) {
this.name = name;
this.isAdmin = false;
}
let user = new User("kim");
console.log(user);
생성자 함수에는 보통 return 없음, 반환해야 할 것들은 모두 this에 저장되고, this는 자동 반환
옵셔널 체이닝 '?.'
옵셔널 체이닝(optional chaining) ?. 을 사용하면 프로퍼티가 없는 중첩 객체에도 에러 없이 안전하게 접근할 수 있습니다.
- 객체의 '숨김' 프로퍼티
- 자바스크립트 내부에서 사용되는 시스템 심볼은 Symbol.* 로 접근 가능.
?. 앞의 평가 대상이 undefined나 null이면 평가를 멈추고 undefined를 반환합니다.
let user = {};
alert(user.address.street); // error :Uncaught TypeError: Cannot read property 'strreet' of undefined
alert(user?.address?.strret); // undefined
- obj?.prob - obj가 존재하면 obj.prop을 반환하고, 그렇지 않으면 undefined를 반환.
- obj?.[prob] - obj가 존재하면 obj[prop]을 반환하고, 그렇지 않으면 undefined를 반환.
- obj?.method() - obj가 존재하면 obj.method()를 호출하고, 그렇지 않으면 undefined를 반환.
심볼형
심볼(Symbol)은 원시형 데이터로 유일한 식별자(unique identifier)를 만들고 싶을 때 사용합니다.
심볼형 값은 다른 자료형으로 암시적 형 변환(자동 형 변환)이 되지 않습니다.
let id = Symbol();
let id2 = Symbol("id");
let id3 = Symbol("id");
let id4 = Symbol("id");
console.log(id3 == id4); // false 심볼은 유일성이 보장되는 자료형이기 때문에, 설명이 동일한 심볼을 여러 개 만들어도 각 심볼값은 다름.
for..in 반복문에서 배제, 직접 접근만 가능.
let id = Symbol("id");
let user = {
user: 'kim',
[id]: 123
};
전역 심볼, 등록, 이름, 찾기
let id = Symbol.for("id"); // 전역 레지스트리에서 심볼 읽음. 존재하지 않으면 새로 만듦.
let idAgain = Symbol.for("id");
console.log(id === idAgain); // true
let sym = Symbol.for("name");
let sym2 = Symbol.for("id");
console.log(Symbol.keyFor(sym));
console.log(Symbol.keyFor(sym2));
객체를 원시형으로 변환하기
- 객체는 논리 평가시 true를 반환합니다. 따라서 객체는 숫자형이나 문자형으로만 형 변환이 일어난다고 생각하시면 됩니다.
- 숫자형으로의 형 변환은 객체끼리 빼는 연산을 할 때나 수학 관련 함수를 적용할 때 일어남.
- 문자형으로의 형 변환은 대게 alert(obj) 같이 객체를 출력하려고 할 때 일어남.
객체 형 변환은 세 종류로 구분됨. (string, number, default-연산자가 기대하는 자료형이 확실치 않을 때)
'hint' : 구분 기준, 목표로 하는 자료형
자바스크립트는 형 변환이 필요할 때, 아래와 같은 알고리즘에 따라 원하는 메서드를 찾고 호출함
- 객체에 obj[Symbol.toPrimitive](hint) 메서드가 있는지 찾고, 있다면 메서드를 호출. Symbol.toPrimitive는 시스템 심볼로, 심볼형 키로 사용.
- 1에 해당하지 않고 hint가 'string'이라면, obj.toString() 이나 job.valueOf() 호출
- 1, 2에 해당하지 않고, hint가 'number'나 'default'라면 obj.valueOf() 나 obj.toString() 호출
let user = {
name: 'kim',
money: 1000,
[Symbol.toPrimitive](hint) {
alert(`hint: ${hint}`);
return hint == "string" ? `{name: "${this.name}"}` : this.money;
}
};
alert(user); // hint: string -> {name: 'kim'}
alert(+user); // hint: number -> 1000
alert(user + 500); // hint: default -> 1500
toString과 valueOf
객체에 Symbol.toPrimitive가 없으면 자바스크립트는 아래 규칙에 따라 toString이나 valueOf를 호출
- hint가 'string'인 경우: toString -> valueOf 순
- 그 외: valueOf -> toString 순
- toString은 문자열 [object Object] 반환
- valueOf는 객체 자신 반환.
let user = {
name: 'kim',
money: 100,
toString () {
return `{name: "${this.name}"}` ;
},
valueOf() {
return this.money;
}
};
alert(user); // toString -> {name: kim}
alert(+user); // valueOf -> 100
alert(user + 500); // valueOf -> 600
'자바스크립트' 카테고리의 다른 글
함수 심화학습, 객체 프로퍼티 설정 (0) | 2020.08.30 |
---|---|
웹 게임을 만들며 배우는 자바스크립트 예제2 (0) | 2020.08.23 |
자료구조와 자료형 (0) | 2020.08.23 |
웹 게임을 만들며 배우는 자바스크립트 (0) | 2020.08.16 |
웹 게임을 만들며 배우는 자바스크립트 예제 (0) | 2020.08.16 |