JavaScript

JavaScript

이 글은 공부를 하면서 정리하는 글이므로 아주 많은 오류를 가지고 있을 수 있다.
블로그 글을 읽지 말고 레퍼런스를 읽자. 현재 이해한 수준으로 정리. 2021.12.14.

closure

https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures

클로저는 함수와 함수가 선언된 execution environment의 조합이다. 접근할 수 없는 lexical scope에 접근하기 위한 함수만을 의미하는 것은 아님. 용어가 미묘하게 엮여있지만...

예) 다른 클로저의 값을 변경한다 => execution environment 내부의 variable을 변경한다. 예) 값에 접근하기 위하여 클로저를 호출한다 => 클로저 execution environment의 내부 변수에 접근하기 위하여 function을 호출한다.

클로저 흔한 실수

실수패턴

function showHelp(help) {
document.getElementById('help').innerHTML = help;
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
for (var i = 0; i < helpText.length; i++) {
var item = helpText[i];
document.getElementById(item.id).onfocus = function() { //클로저 함수. 같은 execution context를 가지므로 같은 item을 가르킴
showHelp(item.help); //<- item이 setupHelp의 execution text에 있는 변수이므로, onfocus시점에서 마지막에 설정된 {'id': 'age', 'help': 'Your age (you must be over 16)'}를 표시함
}
}
}
setupHelp();

해결책

function showHelp(help) {
document.getElementById('help').innerHTML = help; // help는 개별 execution context를 가짐
}
function makeHelpCallback(help) {
return function() {
showHelp(help);
};
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
for (var i = 0; i < helpText.length; i++) {
var item = helpText[i];
document.getElementById(item.id).onfocus = makeHelpCallback(item.help);
}
}
setupHelp();

makeHelpCallBack 함수를 이용해 개별 execution context를 생성함.

execution context

실행 컨텍스트. P

lexical scope

C 라이크 언어와 자바스크립트의 스코프 차이는 클래스 유무에서 발생한다. 클래스 기반 언어에서 상위 스코프의 변수를 참조하지만 변수는 아래 세가지 범위가 있다.

  • 글로벌 범위(global scope)
  • 외부 함수 범위(outer functions scope)
  • 지역 범위(local scope, own scope )

hosting

var 선언된 변수들을 함수의 execution context내에 선언하는 것. (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#var_hoisting) 선언(declaration)들을 함수(execution context) 최상단으로 끌어올려 선언하는 것. 같은 execution context내라면 var로 선언된 변수들은 선언되기 전 사용 가능. => 2022년 개발자라면 let, const 쓰자. 컨텍스트를 참조하기 위해 어느 변수를 가키는지 끌어올리는 것.\<- 아님. 요건 scope chain을 따라 값을 찾는 과정

call, apply, bind

call apply bind

this

this

primitive

객체(object)가 아닌 값.

https://developer.mozilla.org/ko/docs/Glossary/Primitive 이렇게 7개라고 한다.

  • string
  • number(en-US)
  • bigint
  • boolean
  • undefined
  • symbol
  • null

typeof를 찍어보면 뭔가 이상하다. https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/typeof

pritive인데 null은 왜 object?

Type Result Undefined "undefined" Null "object" (아래 참고) Boolean "boolean" Number (en-US) "number" BigInt (en-US) "bigint" String "string" Symbol (ECMAScript 2015에서 추가) "symbol" 호스트 객체 (JS 환경에서 제공) 구현체마다 다름 Function 객체 (ECMA-262 표현으로는 [[Call]]을 구현하는 객체) "function" 다른 모든 객체 "object"

typeof는 아니지만.. Not a number is number

typeof NaN === 'number'

null

값을 할당하지 않음을 표현하는 값. 전역 객체(global object)이다.

https://developer.mozilla.org/ko/docs/Glossary/Null

null은 바로 선넘음. primitive인줄 알았지? typeof는 object란다

typeof null === 'object' // true

undefined

primitive. 타입조차 할당되지 않음을 표현하는 primitive. undefined는 (type) undefined로 이해하면 좋을 듯 하다. primitive인데 예약어가 아니라고 한다. 선넘음...ㅜㅜ

// DON'T DO THIS
// logs "foo string"
(function() {
var undefined = 'foo';
console.log(undefined, typeof undefined);
})();
// logs "foo string"
(function(undefined) {
console.log(undefined, typeof undefined);
})('foo');

참조

[1] 자바스크립트는 왜 프로토타입을 선택했을까 : https://medium.com/@limsungmook/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%8A%94-%EC%99%9C-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85%EC%9D%84-%EC%84%A0%ED%83%9D%ED%96%88%EC%9D%84%EA%B9%8C-997f985adb42 [2] this : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this#dom_%EC%9D%B4%EB%B2%A4%ED%8A%B8_%EC%B2%98%EB%A6%AC%EA%B8%B0%EB%A1%9C%EC%84%9C [3] binding의 개념과 call, apply, bind의 차이점 : https://wooooooak.github.io/javascript/2018/12/08/call,apply,bind/