for … in - hasOwnProperty
{
[Symbol.iterator](){return this;},
data: [{a:[1,2,3,4], b:'-'}, [5,6,7], 8,9],
next(){
let v;
// 아래에 안전장치를 걸어줘야 한다!! max 같은!!
while(v = this.data.shift()) {
switch (true) {
case Array.isArray(v):
this.data.unshift(...v);
break;
// null 이 아니면서 객체인 경우
case v && typeof v == 'object':
let n = [];
// 여기서도 실수 하나 있다.
// if (v.hasOwnProperty()) 를 안 넣어준 것이 실수다.
for (var k in v) n.push(v[k]);
this.data.unshift(n);
break;
default:
return {value:v, done:false};
}
}
return {done: true};
}
}
위의 코드에서 if (v.hasOwnProperty())를 안 넣은 것이 실수다.
for … in 반복문은 proto type에 있는 key까지 다 나오기 때문에 반드시 옆에 hasOwnProperty를 걸어줘야 한다.
{
[Symbol.iterator](){return this;},
data: [{a:[1,2,3,4], b:'-'}, [5,6,7], 8,9],
next(){
let v;
// 아래에 안전장치를 걸어줘야 한다!! max 같은!!
while(v = this.data.shift()) {
if (!v && !(v instanceof Object)) return {value:v};
if (!Array.isArray(v)) v = Object.values(v);
this.data.unshift(...v);
}
return {done: true};
}
}
하지만 위의 식은 이미 그런 기능(hasOwnProperty)을 모두 내재하고 있다.
자기 자신의 프로퍼티만을 가져온다.
자바스크립트 특징 두가지
- 언어 자체의 문법적인 내용으로 되어 있다.
- 모든 언어가 그러하듯이 class library로 되어있다.
자바스크립트의 class library는 코어 객체라고 알려져 있는데, 코어 객체는 무엇일까?
Math, Object, Array, Function, Date, Regular Expression… 등등
이들은 표준으로 제공되고 있는 언어 표준의 일부이다.
자바스크립트 for, while 문들이 표준인 것처럼 자바스크립트가 코어 객체로 제공하고 있는 것들은 Node가 되었건 뭐가 되었건 갖고 있어야되는 표준 객체이다.
이러한 코어 객체도 언어 스펙의 일부이다.
그럼 위 코드에서 쓴 Object.values도 언어 스펙의 일부겠지?
임의대로 이를 우리가 쓰고 싶으면 쓰고, 안 쓰고 싶으면 안 쓰고가 아니라 언어 스펙의 일부이기 때문에 이 기능과 부합하면 당연히 언어 스펙에 있는 사항들을 우선적으로 써야한다.
그래야 에러가 적고 더 올바르게 작동한다.
const Compx = class{
constructor(data) {this.data = data;}
[Symbol.iterator](){
const data = JSON.parse(JSON.stringify(this.data));
return {
next(){
let v;
while (v = data.shift()) {
if (!(v instanceof Object)) return {value:v};
if (!Array.isArray(v)) v = Object.values(v);
data.unshift(...v);
}
return {done: true};
}
};
}
};
const a = new Compx([{a:[1,2,3,4], b:'-'}, [5,6,7], 8,9]);
// console을 여러번 돌려도 상관이없다.
// data가 훼손되지 않는다.
console.log(...a); // 1,2,3,4,'-',5,6,7,8,9
console.log([...a]); // [1,2,3,4,'-',5,6,7,8,9]
ERROR!!
while(v = data.shift()) 구문에서 undefined / null 값이면 끝나는거 아닌가?
위 코드에서 {} 객체 안에 어떤 키값으로 undefined가 들어가있는 경우를 제외하면 null이나 undefined 값이 있으면 while 문으로 가지않고 바로 done:true 리턴되면서 끝날 것이다.
그럼 이전에 while 문 안에서 null 값을 처리해주는 코드를 넣었는데 사실상 필요없는 것이다.
이 문제는 다음에 한번 생각해보자.