2023.06.16
const name = 'answer';
const obj = {
[name]: 42,
};
console.log(obj); // {answer:42}
const prefix = 'ans';
const obj = {
[prefix + 'wer']: 42,
};
console.log(obj); // {answer:42}
function getMinMax(nums) {
let min, max;
// do something
return { min, max };
}
const p1 = {
greet: function () {
console.log('p1 greet' + this.name);
},
};
const p2 = {
greet: function () {
console.log('p2 greet' + this.name);
},
};
const obj = Object.create(p1);
obj.name = 'Joe';
obj.greet();
Object.setPrototypeOf(obj, p2);
obj.greet();
__proto__
속성__proto__
라는 접근자 속성을 사용하여 객체의 프로토타입을 가져오고 설정할 수 있다.
__proto__
기능은 비표준 확장으로서의 동작을 공식적으로 설명하기 위해서만 표준화된 레거시 기능이다. 새 코드에서는 사용하지 않아야 한다. 대신 getPrototypeOf와 setPrototypeOf를 사용하자.
__proto__
리터럴 속성 이름__proto__
는 객체 리터럴에서 결과 객체의 프로토타입을 설정하는 데 사용할 수도 있다.__proto__
접근자 속성의 결과가 아니며 문자 그대로 지정된 경우에만 작동한다.const p = {
hi: function () {
console.log('hi');
},
};
const name = '__proto__';
const obj = {
__proto__: p,
};
obj.hi(); // hi
const obj = {
name: 'Joe',
say() {
console.log(this.name);
},
};
obj.say(); // Joe
const obj = {
toString() {
return super.toString().toUpperCase();
},
};
obj.toString(); // [OBJECT OBJECT]
const obj = {
name() {
return 'test';
},
['say']() {
console.log(this.name());
},
};
obj.say(); // test
const obj = {
toString() {
return super.toString().toUpperCase();
},
};
Object.setPrototypeOf(obj, {
toString() {
return 'a different string';
},
});
obj.toString(); // A DIFFERENT STRING
[object XYZ]
양식의 문자열을 만든다.XYZ
는 생성자의 이름이 된다([object Date]
, [object Array]
등).[object Object]
이다.class Example1 {}
class Example2 {
get [Symbol.toStringTag]() {
return 'Example2';
}
}
new Example1().toString(); // '[object Object]'
new Example2().toString(); // '[object Example2]'
const obj1 = {
[Symbol.toStringTag]: 'Nifty',
};
obj1.toString(); // '[object Nifty]'
const MySymbol = Symbol('my symbol');
MySymbol.description; // my symbol
const everUpward = (() => {
const count = Symbol('count');
return {
[count]: 0,
increment() {
return ++this[count];
},
get() {
return this[count];
},
};
})();
console.log(everUpward.get()); // 0
everUpward.increment();
console.log(everUpward.get()); // 1
console.log(everUpward['count']); // undefined
console.log(everUpward[Symbol('count')]); // undefined
const s = Symbol.for('my-nifty-symbol');
const key = Symbol.keyFor(s);
console.log(key); // "my-nifty-symbol"
// Not in the global registry:
const s2 = Symbol('my-nifty-symbol');
const key2 = Symbol.keyFor(s2);
console.log(key2); // undefined
console.log(Object.is(+0, -0)); // false
console.log(Object.is(NaN, NaN)); // true
const obj = {
a: 1,
b: 2,
c: 3,
};
console.log(Object.values(obj)); // [1, 2, 3]
[이름, 값]
배열의 배열을 제공하는 Object.entries도 추가됐다.const obj = {
a: 1,
b: 2,
c: 3,
};
console.log(Object.entries(obj)); // [["a", 1], ["b", 2], ["c", 3]]
const obj = Object.fromEntries([
['a', 1],
['b', 2],
['c', 3],
]);
console.log(obj);
// => {a: 1, b: 2, c: 3}
const s = Symbol('example');
const o1 = {
// 심볼로 정의된 속성
[s]: 'one',
// 접근자 속성
get example() {
return this[s];
},
set example(value) {
this[s] = value;
},
// 데이터 속성
data: 'value',
};
// 열거할 수 없는 속성
Object.defineProperty(o1, 'nonEnum', {
value: 42,
writable: true,
configurable: true,
});
// 해당 속성을 새 겍체에 복사
const descriptors = Object.getOwnPropertyDescriptors(o1);
const o2 = Object.defineProperties({}, descriptors);
console.log(o2.example); // "one"
o2.example = 'updated';
console.log(o2[s]); // "updated", [s]에 작성된 속성
console.log(o2.nonEnum); // 42
console.log(o2.data); // "value"
// Object.assign와 비교
const o3 = Object.assign({}, o1);
console.log(o3.example); // "one"
o3.example = 'updated';
console.log(o3[s]); // "one", example는 접근자가 아니라 단지 데이터 속성이므로 one이 출력 됨.
console.log(o3.nonEnum); // undefined
console.log(o3.data); // "value"
number
, string
, default
)로 받는다.const obj = {
[Symbol.toPrimitive](hint) {
const result = hint === "string" ? "str" : 42;
console.log("hint = " + hint + ", returning " + JSON.stringify(result));
return result;
},
};
/*
더하기 연산자를 사용하면 선호도가 없기 때문에
Symbol.toPrimitive 메서드는 다음과 같이 'default'로 호출된다.
*/
console.log("foo" + obj);
// hint = default
// foo42
console.log(2 + obj);
// hint = default
// 44
/*
빼기 연산자이면 다음과 같이 힌트는 'number'이다.
*/
console.log(2 - obj);
// hint = number
// -40
/*
문자열이라면 힌트는 'string'이다.
*/
console.log(String(obj));
// hint = string
// str
console.log("this is a string".indexOf(obj));
// hint = string
// 10 (the index of "str" in "this is a string")
for-in
루프, Object.keys
, Object.values
, Object.entries
, Object.getOwnPropertyNames
, JSON.stringify
등에서 반환된 배열에 적용되지 않았다.Object.assign
호출 대신 객체 리터럴 내에서 표현식 앞에 줄임표(…)를 사용하여 표현식 결과의 고유한 열거 가능한 속성을 스프레드 할 수 있다.function showDialog(opts) {
const options = { ...defaultOptions, ...opts };
console.log("title = '" + options.title + "', text = '" + options.text + "'");
}
Object.assign
과 거의 똑같이 작동한다.**Object.assign
는 기존 객체에 할당 할 수 있는 반면 속성 스프레드는 새 객체를 만들 때만 사용할 수 있다.**…를 연산자로 생각하고 싶은 유혹이 있겠지만, 연산자가 아니며 그럴 수도 없다. 연산자는 함수와 같다. 피연산자가 있고 단일 결괏값을 생성한다. 그러나 결괏값은 객체에서 이러한 속성 생성이라고 말할 수 없다. 따라서 줄임표는 기본 구문/표기이다. 즉 연산자가 아니며 while 루프의 조건을 둘러싼 괄호와 같다.
let name = 'answer';
let obj = {
[name]: 42,
};
function getMinMax() {
let min, max;
// ...
return { min, max };
}
Object.assign
을 사용하거나 모든 속성을 명시적으로 복사Object.assign
을 사용하자.__proto__
대신 Object.getPrototypeOf
/ Object.setPrototypeOf
사용__proto__
가 표준화되었음에도 Object.getPrototypeOf
와 Object.setPrototypeOf
를 사용하자.super
를 사용하는 경우 메서드는 원래 객체에 대한 링크를 가지므로 다른 객체에 복사하면 새 객체가 아닌 원래 객체의 프로토타입을 계속 사용한다.super
를 사용하지 않으면 좋은 자바스크립트 엔진이 해당 링크를 최적화한다.