iterator 는 소스 데이터에 대한 참조를 갖고 다음 일부를 return하는 next()
같은 method를 쓰는 데이터 구조. next는 iterator result로 객체로 value 와 done을 property를 갖고 있다.
하지만 위는 수동적. for..of
(for(let a of b)
),...
(spread, rest)
반복될 수 있는 것들을 말한다. 프로토콜(?)은 이로부터 자동으로 iterator instance를 만든다.
종류:strings, arrays, maps, sets, and others.
Map
데이터 구조는 객체를 키로 사용하여 그 객체랑 값(모든유형)을 연결하며 tuple(2-ele array) entries가 넘겨진다.
// given two DOM elements, `btn1` and `btn2`
var buttonNames = new Map();
buttonNames.set(btn1,"Button 1");
buttonNames.set(btn2,"Button 2");
for (let [btn,btnName]/*array destrucurting*/ of buttonNames) {
btn.addEventListener("click",function onClick(){
console.log(`Clicked ${ btnName }`);
});
}
iterable forms : keys(), values(), entries()
Closure is when a function remembers and continues to access variables from outside its scope, even when the function is executed in a different scope.
function greeting(msg) {
return function who(name) {
console.log(`${ msg }, ${ name }!`);
};
}
var hello = greeting("Hello");//inner function instance
var howdy = greeting("Howdy");
hello("Kyle");
// Hello, Kyle!
hello("Sarah");
// Hello, Sarah!
howdy("Grant");
// Howdy, Grant!
msg grabage collected(메모리에서 삭제) 상태가 아님. 또한, snapshot이 아닌 direct link.
비동기 코드에 흔하다. callback 같은.
function getSomeData(url) {
ajax(url,function onResponse(resp){
console.log(
`Response (from ${ url }): ${ resp }`
);
});
}
getSomeData("https://some.url/wherever");
// Response (from https://some.url/wherever): ...
바깥 범위가 함수일 필요가 없다. 주의해야할 점은 숫자에 클로징된 것이 아니라 변수에 클로징 됐다는 것.
for (let [idx,btn] of buttons.entries()) {
btn.addEventListener("click",function onClick(){
console.log(`Clicked on button (${ idx })!`);
});
}
this
Keywordthis의 많은 오해. 함수자체나 method가 속한 인스턴스를 가리키는 것이 아니다.
스코프는 함수에 정의한 순간이나 장소에 영향을 받아 정적인 반면, 실행 컨텍스트는 어디에 정의되고 호출됐는지보다 어떻게 호출되었는지에 의존한다. 즉, this는 함수 호출 시마다 결정된다.
그리고 실행 컨텍스트는 함수를 실행 시, 함수에서 속성을 사용할 수 있는 객체라고 생각할 수 있다.
function classroom(teacher) {
return function study() {
console.log(
`${ teacher } says to study ${ this.topic }`
);
};
}
var assignment = classroom("Kyle");
assignment();//딱히 실행 컨텍스트를 주지 않았다.
// Kyle says to study undefined -- Oops :(
엄격모드가 아니라서 컨텍스트를 특정하지 않은 context-aware 함수는 자동으로 전역객체가 컨텍스트로 정해진다.
var homework = {
topic: "JS",
assignment: assignment
};
homework.assignment();
// Kyle says to study JS
var otherHomework = {
topic: "Math"
};
assignment.call(otherHomework);
// Kyle says to study Math
this를 잘 이용하면 참조하는데 용이할 수 있다.
객체 두 개를 생성했을 때 사실 별다른 행동을 하지 않아도 둘은 연결되어 있다. 프로토타입으로 연결된 일련의 객체들을 prototype chain이라고 한다.
가령, 객체 a,b가 있다고 가정했을 때, a에서 처리할 수 없는 접근을 b에게 위임하여 처리할 수 있다.
var homework = {
topic: "JS"
}; //기본 내장 메소드 갖고 있는 Object.prototype에 연결되어 있다.
homework.toString();
객체 프로토타입 연결을 정의하기 위해서Object.create(..)
사용할 수 있다.
연결할 객체를 인자로 받아 생성하여 return. 즉, 연결되어 있다. null을 넣으면 어디에도 연결되지 않는다.
var homework = {
topic: "JS"
};
var otherHomework = Object.create(homework);
homework.topic;
// "JS"
otherHomework.topic;
// "JS"
otherHomework.topic = "Math";
otherHomework.topic;
// "Math"
homework.topic;
// "JS" -- not "Math"
다만,프로토타입 체인을 통한 위임은 속성의 값을 조사를 위한 접근만 가능하고 속성을 할당하려고 하면 해당 객체에만 적용된다. 즉, otherHomework의 topic이 쉐도잉 한 것.
프로토타입 연결을 사용해서 객체 생성하는 더 흔한 방법이 있음. prototyparl class를 사용하는 방법.
this
Revisited체인에서 프로토타입-위임된 함수 호출시 this가 매우 유용.
var homework = {
study() {
console.log(`Please study ${ this.topic }`);
}
};
var jsHomework = Object.create(homework);
jsHomework.topic = "JS";
jsHomework.study();
// Please study JS
var mathHomework = Object.create(homework);
mathHomework.topic = "Math";
mathHomework.study();
// Please study Math
즉, 해당객체를 가리킴