June 27, 2022
정리 안 됨
변수 shadowing: 가장 먼저 찾아진 것만 찾아 갈 수 있는 것
with
문eval()
let
의 문제// 원시 값
let foo = 5;
// 원시 값을 변경해야 하는 함수 정의
function addTwo(num) {
num += 2;
}
// 같은 작업을 시도하는 다른 함수
function addTwo_v2(foo) {
foo += 2;
}
// 원시 값을 인수로 전달해 첫 번째 함수를 호출
addTwo(foo);
// 현재 원시 값 반환
console.log(foo); // 5
// 두 번째 함수로 다시 시도
addTwo_v2(foo);
console.log(foo); // 5
JS는 인터프리터인가? 컴파일러인가?
함수를 실행할 때 필요한 환경정보를 담은 객체이다
Execution Context 객체
Lexical Environment: 값이 바뀔 때 변경사항을 계속 추적
eval
strict부터는 새로운 eval을 위한 스콥을 추가
컴파일러의 단계에서 온 것임
어떻게 어디서 어떤 Scope에서 선언됐는지 1도 신경 안 씀
function foo() {
console.log( a ); // 2? 3?
}
function bar() {
var a = 3;
foo();
}
var a = 2;
bar();
eval
위에서 언급함.
eval
보다 위험한 with
lexical scope을 망치는 또 다른 놈
var obj = {
a: 2,
b: 3,
c: 4
};
obj.a = obj.b + obj.c;
obj.c = obj.b - obj.a;
with (obi) {
a = b+ c;
d = b - a;
d = 3; // ??
}
obj.d; // undefined
d; // 3 !!
line 13: d
는 뭐야
- with
도 Lexical Scope이랑 똑같이 작동해..
- 새로운 Lexical Scope을 런타임에 생성해…
- 컴파일러가 이걸 보는 순간 가장 최악을 가정하고 많은 최적화 옵션을 끄게 됨
ben ellman?
블로그에 올림
Encapsulation, Protection, Abstraction, Information hiding - 코드가 길어지면 - 글로벌 네임스페이스, 콜리션되는 것을 보호하기 위해 - 1000개의 함수가 있는데 1개만 글로벌이길 원한다면?
어떻게 함수나 변수를 숨길까?
function -> decl
(function)-> exppr
expr() -> 바로 실행
(funciton(global){
// private
global.aa = 23
})(window);
(es5)
function foo() {
var bar = "bar"
for (let i = 0; i < bar.length; i++) {
console.log(bar.charAt(i));
}
console.log(i); // i는 for문을 위한 것!@!!
}
foo();
for(var i=1; i<6; i++){
setTimeout(function(){
console.log(i);
},1000)
}
for(let i=1; i<6; i++){
setTimeout(function(){
console.log(i);
},1000)
}
if
stmt에도 같은 이유로
성능 좋아
var
은 함수 전체에 묶인다let
의 문제hoist안 됨 -> 공식문서상 됨
let
을 넣어야 됨말이 많음… => 호이스팅은 되지만 초기화가 안 된다
temporally dead zone
eval
돼야지 initialize리팩터링할 때 추가적으로 블럭을 신경써야됨
var
는 함수면 상관 없음Implicit하다
let
일 수도 아닐 수도중간에 가다가 let
으로 선언될 수도..
if(a) {
console.log(b); // temporal dead zone
let b = a;
}
Explicit한 새로운 문법
function foo(bar) {
let (baz=bar) {
console.log(baz) // "bar"
}
console.log(baz) // Error
}
foo("bar")
let
이 쓰인다는 것이 확실function foo(bar) {
/*let*/ { let baz = bar;
console.log(baz) // "bar"
}
console.log(baz) // Error
}
foo("bar")
없는 기능을 JS로 transpile
tc39에서 let
을 테스트할 때 쓰는 transpiler(tracer: google)
try(throw void 0)catch
/*let*/ (foo) {
foo = "foo";
console.log(foo)l // "foo"
}
foo // ref error
공식 spec에서는 없는 단어 그냥 설명하기 위한 단어임
a;
b;
var a = b;
var b = 2;
b;
a;
hoist
는 이러한 Compile Phase를 설명하기 위한 개념적인 것
코드 1의 hoist
var a;
var b;
a;
b;
a = b;
b = 2;
b;
a;
var a = b();
var c = d();
a; // ?
c; // ?
function b() {
return c;
}
var d = function() {
return b();
}
=> // d is not a func
코드 2의 hoist
function b() {
return c;
}
var a;
var c;
var d;
a = b();
c = d();
a;
c;
d = function() {
return b();
}
foo();
var foo = 2;
function foo() {
console.log("bar");
}
function foo() {
console.log("foo");
}
호이스트 과정
Function은 hoist로 덮힐수도 있음
이미 foo
라는 변수가 있으므로 var foo
선언은 무시 됨.
교훈: 같은 이름을 쓰지말자..
호이스팅(컴파일타임에 변수를 다 끌어오는 것)이 왜 필요할까?