스코프
- 함수 안에서 선언된 지역 변수는 해당 함수 안에서만 쓸 수 있다.
var x = 'global';
function ex() {
var x = 'local';
x = 'change';
}
ex();
alert(x);
- 함수를 실행해서 x를 바꾸어도 전역 변수의 값은 변하지 않는다.
var x = 'global';
function ex() {
x = 'change';
}
ex();
alert(x);
- 자바스크립트는 변수의 범위를 호출한 함수의 지역 스코프부터 전역 변수들이 있는 전역 스코프까지 점차 넓혀가며 찾는다.
- 함수 내부에서 x를 못 찾으니 전역 변수를 추적.
스코프 체인
var name = 'zero';
function outer() {
console.log('외부', name);
function inner() {
var enemy = 'nero';
console.log('내부', name);
}
inner();
}
outer();
console.log(enemy);
- 내부 함수에서는 외부 함수의 변수에 접근 가능하지만 외부 함수에서는 내부 함수의 변수에 접근할 수 없다.
- 모든 함수들은 전역 객체에 접근할 수 있다.
- 꼬리를 물고 계속 범위를 넓히면서 찾는 관계를 스코프 체인이라 부른다.
렉시컬 스코핑(lexical scoping)
var name = 'zero';
function log() {
console.log(name);
}
function wrapper() {
var name = 'nero';
log();
}
wrapper();
- 스코프는 함수를 호출할 때가 아니라 선언할 때 생긴다.
- log 안의 name은 wrapper 안의 지역변수 name이 아니라, 전역변수 name을 가리키고 있다.
- 함수를 처음 선언하는 순간, 함수 내부의 변수는 자기 스코프로부터 가장 가까운 곳(상위 범위에서)에 있는 변수를 계속 참조하게 된다.
- 위의 예시에서는 log 함수 안의 name 변수는 선언 시 가장 가까운 전역변수 name을 참조하게 된다.
var name = 'zero';
function wrapper() {
var name = 'nero';
function log() {
console.log(name);
}
log();
}
wrapper();
- log 함수가 wrapper 내부에 있다면 log의 name은 상위 범위인 wrapper의 name을 가리키게 된다.
IIFE(즉시 호출 함수 표현식)(모듈 패턴)
var newScope = (function () {
var x = 'local';
return {
y: function() {
alert(x);
}
};
})();
- 라이브러리를 만들 때 기본으로 쓰이는 방식.
(function() {})();
구문은 즉시 호출 함수 표현식으로, 함수를 선언하자마자 동시에 실행하는 것을 의미한다.
컨텍스트
- 컨텍스트 == 문맥
- 함수를 실행하자마자 모든 것을 포함하는 전역 컨텍스트가 생성된다.
- 함수를 호출할 때마다 함수 컨텍스트가 하나씩 더 생긴다.
컨텍스트의 원칙
- 먼저 전역 컨텍스트 하나 생성 후, 함수 호출 시마다 컨텍스트가 생성.
- 컨텍스트 생성 시 컨텍스트 안에 변수객체(arguments, variable), scope chain, this가 생성.
- 컨텍스트 생성 후 함수가 실행되는데, 사용되는 변수들은 변수 객체 안에서 값을 찾고, 없다면 스코프 체인을 따라 올라가며 찾음.
- 함수 실행이 마무리되면 해당 컨텍스트는 사라짐.(클로저 제외) 페이지가 종료되면 전역 컨텍스트가 사라짐.
var name = 'zero';
function wow(word) {
console.log(word + ' ' + name);
}
function say () {
var name = 'nero';
console.log(name);
wow('hello');
}
say();
전역 컨텍스트
- 전역 컨텍스트가 생성된 후 두 번째 원칙에 따라 변수객체, scope chain, this가 들어온다.
- 전역 컨텍스트는 arguments(함수의 인자를 말합니다)가 없고, variable은 해당 스코프의 변수들이다.
- scope chain(스코프 체인, 자신과 상위 스코프들의 변수객체)은 자기 자신인 전역 변수객체.
- this는 따로 설정되어 있지 않으면 window.
- this를 바꾸는 방법이 바로 new를 호출하거나 함수에 다른 this 값을 bind하는 것.
'전역 컨텍스트': {
변수객체: {
arguments: null,
variable: ['name', 'wow', 'say'],
},
scopeChain: ['전역 변수객체'],
this: window,
}
- 객체 형식으로 표현.
- wow랑 say는 호이스팅 때문에 선언과 동시에 대입.
- 그 후 variable의 name에 'zero'가 대입.
variable: [{ name: 'zero' }, { wow: Function }, { say: Function }]
함수 컨텍스트
- (7)번에서
say();
를 하는 순간 새로운 컨텍스트인 say 함수 컨텍스트가 생성.
- arguments는 없고, variable은 name.
- scope chain은 say 변수객체와 상위의 전역 변수객체.
- this는 따로 설정해준 적이 없으니 window.
'say 컨텍스트': {
변수객체: {
arguments: null,
variable: ['name'],
},
scopeChain: ['say 변수객체', '전역 변수객체'],
this: window,
}
- say를 호출한 후 위에서부터 차례대로((8)~(10) 실행.
- variable의 name에 nero를 대입해주고 나서
console.log(name);
의 name 변수는 say 컨텍스트 안에서 찾음(nero).
wow('hello')
에서 say 컨텍스트 안에서 wow 변수를 찾을 수 없기에 scope chain을 따라 올라가 상위 변수객체에서 추적.
- 전역 변수객체의 variable에 wow 함수 호출.
- (10)번에서 wow함수가 호출함에 따라 wow 컨텍스트 생성.
- arguments는 word = 'hello'고, variable은 없음.
- scope chain은 wow 스코프와 전역 스코프.
- lexical scoping에 따라 wow 함수의 스코프 체인은 선언 시에 이미 정해져 있다.
- say 스코프는 wow 컨텍스트의 scope chain이 아님.
- this는 똑같이 window.
'wow 컨텍스트': {
변수객체: {
arguments: [{ word : 'hello' }],
variable: null,
},
scopeChain: ['wow 변수객체', '전역 변수객체'],
this: window,
}
- 컨텍스트가 생긴 후 함수가 실행 됩니다.
console.log(word + ' ' + name);
에서 word랑 name 변수는 wow 컨텍스트에서 추적.
- word는 arguments 에서 찾을 수 있다.
- name은 wow 변수객체에는 값이 없으니, scope chain을 따라 전역 스코프에서 찾는다.
- 전역 변수객체의 variable에 name(zero) 추적.
- 결과값은 hello zero.
- 만일 wow 함수가 say 함수 내부에 있었다면 say 스코프가 wow 컨텍스트의 스코프 체인이 됨으로써 hello nero가 되었을 것.
- wow 함수 종료 후 wow 컨텍스트 소멸, say 함수의 실행 마무리.
- 따라서 say 컨텍스트도 사라지고, 마지막에 전역 컨텍스트도 소멸.
호이스팅
- 호이스팅이란 변수를 선언하고 초기화했을 때 선언 부분이 최상단으로 끌어올려지는 현상을 의미한다.
console.log(zero);
sayWow();
function sayWow() {
console.log('wow');
}
var zero = 'zero';
- sayWow처럼 함수 표현식이 아니라 함수 선언식일 때는 식 자체가 통째로 끌어올려진다.
- 위의 코드는 선언보다 호출을 먼저 하지만 변수 선언과 함수 선언식이 최상단으로 끌어올려졌기 때문에 에러 없이 정상 작동한다.
function sayWow() {
console.log('wow');
}
var zero;
console.log(zero);
sayWow();
zero = 'zero';
- 변수의 선언과 대입을 동시에 한 경우에는 선언 부분만 우선 실행된다.
sayWow();
sayYeah();
var sayYeah = function() {
console.log('yeah');
}
function sayWow() {
console.log('wow');
}
- 함수 표현식으로 선언한 경우에는 에러가 발생한다.
'전역 컨텍스트': {
변수객체: {
arguments: null,
variable: [{ sayWow: Function }, 'sayYeah'],
},
scopeChain: ['전역 변수객체'],
this: window,
}
- 실행 시 전역 컨텍스트가 먼저 생성.
- sayWow 함수는 함수 선언식이므로 컨텍스트 생성 후 바로 대입.
- 컨텍스트 생성 및 코드가 순차적으로 실행되는데 sayYeah는 대입되기 전에 호출해서 에러가 발생.
- 변수로서의 sayYeah는 선언되었으나 대입 부분은 그자리에 그대로 있기 때문.
===란?
- 자바스크립트에서 ==는 단순히 값이 유효하냐 아니냐만을 체크
- ===는 데이터 타입까지도 고려한다.
onChange? onSubmit?
preventDefault?
- a 태그나 submit 태그는 누르게 되면 href 를 통해 이동하거나 , 창이 새로고침하여 실행된다.
- 페이지가 새로 고침 되는 것을 막고 싶을 때 사용된다.
e.target.value
- 현재 input의 들어온 값을 받을 수 있다.
this?
- 기본적으로 window를 가리킨다.
- 메서드 안에서는 해당 메서드를 가리킨다.
- 호출하는 함수가 객체의 메서드가 아닌 그냥 함수라면 window를 가리킨다.
- bind, call, apply를 사용하면 this가 객체를 가리킨다.
- 객체를 만드는 생성자 함수의 경우 new를 쓰지 않으면 window를 가리키게 된다.
- new를 사용하면 생성된 인스턴스를 가리킨다.
$('div').on('click', function() {
console.log(this);
const inner = () => {
console.log('inner', this);
}
inner();
});
- react에서 이벤트가 발생할 때는 내부적으로 window가 아닌 클릭한 객체(div)를 가리키게 된다.
- 그런데 함수에서의 this는 window를 가리킨다.
- ES6 화살표 함수를 써서 this로 window 대신 상위 함수의 this를 가져오게 할 수 있다.(여기서는
)
화살표 함수?
콜백 함수?
- 인자로 함수를 전달받아, 함수의 내부에서 실행하는 함수.
- 자바스크립트는 null 과 undefined 타입을 제외하고 모든 것을 객체로 다룬다.
- 함수를 변수 or 다른 함수의 변수처럼 사용할 수 있다. 함수를 콜백함수로 사용할 경우, 함수의 이름만 넘겨주면 된다.
비동기
- 동기 : 요청이 들어온 순서에 맞게 하나씩 처리하는 방식이다. 순서에 맞춰 진행되는 장점이 있지만, 여러 가지 요청을 동시에 처리할 수 없다.
- 비동기 : 하나의 요청에 따른 응답을 즉시 처리하지 않아도, 그 대기 시간동안 또 다른 요청에 대해 처리 가능한 방식이다. 여러 개의 요청을 동시에 처리할 수 있는 장점이 있지만 동기 방식보다 속도가 떨어질 수도 있다.
- 자바스크립트에서 커다란 데이터를 가져온다고 했을 때 동기적이라면 데이터를 가져올 때까지 아무것도 하지 못한다.
- 이를 방지하기 위한 방법이 비동기. 콜백 함수와 연관이 있다.
- 비동기적으로 처리하기에 특정 데이터를 이용하려고 할 때 데이터를 받을 때까지 기다릴 필요가 있다.
클래스
생성자
super란?
- 자바스크립트에서 super 는 부모클래스 생성자의 참조이다.
- 자바스크립트는 언어적 제약사항으로서 생성자에서 super 를 호출하기 전에는 this 를 사용할 수 없다.
왜 props를 인자로 전달?
- props 속성을 초기화하기 위해 부모 컴포넌트에게 props 를 전달하는 것.
- super(props)를 적지 않으면
this.props
문법이 불가능.
https://opentutorials.org/module/4047