#오늘 배운 것
LexicalEnvironment(1) - environmentRecord와 호이스팅
현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장(수집)
수집 대상 정보 : 함수에 지정된 매개변수 식별자, 함수 자체, var로 선언된 변수 식별자 등
컨텍스트 내부를 처음부터 끝까지 순서대로 훑어가며 수집(실행하지는 X)
호이스팅
변수정보 수집을 모두 마쳤더라도 아직 실행 컨텍스트가 관여할 코드는 실행 전 의 상태임(JS 엔진은 코드 실행 전 이미 모든 변수정보를 알고 있는 것)
변수 정보 수집 과정을 이해하기 쉽게 설명한 ‘가상 개념’

함수 정의
function a () { /* ... */ } // 함수 선언문. 함수명 a가 곧 변수명. 선언 그 자체
//괄호 앞에 적힌 a가 곧 변수명
a(); // 실행 ok
var b = function () { /* ... */ } // (익명 함수 표현식. 변수명 b가 곧 변수명
//function 뒤에 아무것도 없어서 익명
b(); // 실행 ok
var c = function d () { /* ... */ } // 기명 함수 표현식. 변수명은 c, 함수명은 d
//좌측 변수명, 우측 function과 함수명. d는 c함수 내부의 사용될 수 있는 것이고 외부에서 호출은 X
c(); // 실행 ok
d(); // 에러!
- 함수 선언문의 경우 함수 그 자체가 호이스팅 된다.
- 함수 표현식은 변수와 비슷..
if. 기존의 선언문 과 새로운 선언문을 호이스팅한다면
밑에 있는 선언문이 위에있는 선언문을 덮기 때문에 영향이 간다. 그러므로 주의해서 사용해야 할 것.
LexicalEnvironment(2) - 스코프, 스코프 체인, outerEnvironmentReference(=outer)
스코프
식별자에 대한 유효범위 ..식별자가 유효한 범위
대부분 언어에서 존재하며, JS에서도 존재(es5 / es6는 조금 다름)
es6는 js의 최신버전이라고 생각하면 된다.
Q.let const 대신 var를 안써도 되지 않나?
A.예전 var를 쓰는 코드들이 많기 때문에 사용해야할 수 도 있다.
스코프 체인 == 단방향 (스코프가 연결 되어있다.)
- 식별자의 유효범위를 안에서부터 바깥으로 차례로 검색해나가는 것
- outer는 현재 호출된 함수가 선언될 당시의 LexicalEnvironment를 참조
- ex) A함수 내부에 B함수 선언 → B함수 내부에 C함수 선언(Linked List)
- 오직 자신이 선언된 시점의 LexicalEnvironment를 참조하고 있으므로, 가장 가까운 요소부터 차례대로 접근 가능
- >>>무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에게만 접근이 가능

var a 호이스팅 되면서 console.log(a)는 undefined값이 출력된다 . inner함수의 스코프는 내부의 a를 찾은 것이기 때문.
> 다음 inner함수 호출이 끝나면서 다음console.log(a)는 inner함수가 out됐기 때문에 outer 내 함수는a가 없기 때문에 전역 컨텍스트의 1을 출력한다. > 다음 console.log는 전역콘텍스트값이 있기 때문에 1을 출력
스코프상에 존재하지 않으면 record > outer의 적시된 record순서로 찾아가서 함수를 찾는다 == 이것이 스코프체인.
outer
스코프 체인이 가능토록 하는 것(외부 환경의 참조정보)
this
this는 곳 클래스로 생성한 인스턴스를 말합니 다. 그러나 자바스크립트에서는 this가 어디에서나 사용될 수 있다.
실행컨텍스트가 생길 때, 마지막에 this binding을 하는데 그 this를 묶는 것이다.
->this는 실행 컨텍스트가 생성될 때 결정(this binding) === this는 함수를 호출할 때 결정
전역 공간에서의 this
전역 공간에서 this는 전역 객체를 가리킴
window(브라우저 환경), global(node 환경)
메서드로서 호출할 때 그 메서드 내부에서의 this
함수 vs 메서드
1. 기준 : 독립성
함수 : 그 자체로 독립적인 기능을 수행 ex)obj1.함수명이 아니라 함수명( )으로 호출.
메서드 : 자신을 호출한 대상 객체에 관한 동작을 수행 ex)obj1.함수명()
var func = function (x) {
console.log(this, x); //this는 window객체, 함수로서 호출된거라면 this는 window객체로 의미)
};
func(1); // Window { ... } 1
var obj = {
method: func,
};
obj.method(2); // { method: f } 2 여기의 this는 obj의 객체다.
함수로서의 호출(독립적)과 메서드로서의 호출 구분 기준 : . []
함수로서 호출할 때(독립적) 그 함수 내부에서의 this
호출의 주체를 명시할 수 없으므로 this는 지정할 수 없다.
실행컨텍스트를 활성화할 당시 this가 지정되지 않은 경우(this가 지정될려면 주체가 명확해야한다.), this는 전역 객체를 바라봄.따라서, 함수로서 ‘독립적으로’ 호출할 때는 this는 전역 객체(즉 window)
메서드(주체가 명확하다)의 내부함수에서의 this
메서드의 내부라고 해도, 함수로서 호출한다면 this는 전역 객체

예시의 경우 함수로써의 호출인지에 메소드로써의 호출인지에 따라 this의 역할이 달라진다.
>>this 바인딩에 관해서는 함수를 실행하는 당시의 주변 환경(메서드 내부인지, 함수 내부인지)은 중요하지 않고, 오직 해당 함수를 호출하는 구문 앞에 점 또는 대괄호 표기가 있는지가 관건임!
메서드의 내부 함수에서의 this 우회
1. 변수 활용
var obj1 = {
outer: function() {
console.log(this);
var innerFunc1 = function() {
console.log(this);
}
innerFunc1();//this == window. 코드의 실행부. console.log(this);호출
var self = this; //self변수에 this를 할당해버린다.여기의 this obj1의 outer이기 때문에 호출주체가 내부에 존재하게 된다.
var innerFunc2 = function() {
console.log(self);
};
innerFunc2();
}
};
obj1.outer();//실제 실행부분
화살표 함수(es6부터 도입)
실행 컨텍스트를 생성할 때 this 바인딩 과정 자체가 없음.따라서, this는 이전의 값-상위값-이 유지됨
var obj = {
outer: function() {
console.log(this); //obj
var innerFunc = () => {
console.log(this);
};
innerFunc();//여기까지 호출문. 함수로써 호출임에도 function이 아닌 화살표로 호출했으니 this binding을 생략한다.
}
}
obj.outer(); //호출
콜백 함수 호출 시 그 함수 내부에서의 this
setTimeout(function () { console.log(this) }, 300); //window
[1, 2, 3, 4, 5].forEach(function(x) {
console.log(this, x); //window
});
document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a').addEventListener('click', function(e) {
console.log(this, e); //querySeletor('#a') : 버튼 태그
});
- setTimeout 함수, forEach 메서드는 콜백 함수를 호출할 때 대상이 될 this를 지정하 지 않으므로, this는 곧 window객체 .foreach문에 this를 명시를 해준다면 출력은 된다.위 예시는 없으므로 window.
- setTimeout , forEach는 콜백함수를 넘겨주는 과정에서 this를 잃어버린다.setTimeout은 function()함수로 주면 this를 잃어버리고 전역객체가 된다. 그래서 window객체가 되는 것.foreach의 function도 함수 객체이기 때문에 window다.
- addEventListner 메서드는 콜백 함수 호출 시, 자신의 this를 상속하므로, this는 addEventListner의 앞부분(button 태그)
생성자 함수 내부에서의 this
생성자 : 구체적인 인스턴스를 만들기 위한 일종의 틀
var Cat = function (name, age) {
this.bark = '야옹';
this.name = name;
this.age = age;
};
var choco = new Cat('초코', 7); //this : choco
var nabi = new Cat('나비', 5); //this : nabi
//생성사 내부의 this는 인스턴스를 가리킨다.
명시적 this 바인딩(자동으로 부여되는 상황별 this의 규칙을 깨고 this에 별도의 값을 저장하는 방법)
call 메서드
호출 주체인 함수를 즉시 실행하는 명령어
var func = function (a, b, c) {
console.log(this, a, b, c);
};
func(1, 2, 3); // Window{ ... } 1 2 3
func.call({ x: 1 }, 4, 5, 6}; // { x: 1 } 4 5 6
.뒤에call을 붙이고, 메소드를 통해 인자를 주기 전 원하는 this binding을 주게 된다.
this binding 객체와 ,를 통해 추가적으로 매개변수를 할당한다.
apply 메서드
call 메서드와 완전 동일
두 번째 인자가 [ ] 배열인 부분만 다름
call / apply 메서드 활용
유사배열객체(array-like-object)에 배열 메서드를 적용
- 객체지만 배열처럼 동작할 수 있도록 구조를 잡은 객체
- 반드시 length가 필요하고, index번호가 0부터 시작해서 ++되야한다.
//객체에는 배열 메서드를 직접 적용할 수 없어요.
//유사배열객체에는 call 또는 apply 메서드를 이용해 배열 메서드를 차용할 수 있어요.
var obj = {
0: 'a',
1: 'b',
2: 'c',
length: 3
};
Array.prototype.push.call(obj, 'd'); //유사배열이지만 push할 수 있다.
console.log(obj); // { 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }
var arr = Array.prototype.slice.call(obj);
console.log(arr); // [ 'a', 'b', 'c', 'd' ]
slice() 배열로 부터 특정 범위를 복사한 값들을 담고 있는 새로운 배열을 만드는데 사용합니다. 첫번째 인자로 시작 인덱스(index), 두번째 인자로 종료 인덱스를 받으며, 시작 인덱스부터 종료 인덱스까지 값을 복사하여 반환
arguments, NodeList에 배열 메서드를 적용
arguments
function a () {
console.log('a메서드 호출);
var argv = Array.prototype.slice.call(arguments); //array에 속해있는 slice를 가져왔다.
//argv : 배열
argv.foreach(function(arg) {
console.log(arg)
})
}
a();
//node.js를 터미널에 치면 console이 잘 찍힌다.
//a라는 함수가 매개변수는 없지만 아무것도 없는 함수를 호출할 때 매개변수 대신 인자값으로 쓸수 있는 값.
NodeList
document.body.innerHTML = '<div>a</div>''<div>b</div>''<div>c</div>';
var nodeList = document.querySelectorAll('div'); //div태그가 있는것을 전부 가져옴
var nodeArr = Array.prototype.slice.all(nodeList);
nodeArr.foreach(function(node) {
console.log(node);
});
'[내일배움캠프] > TIL' 카테고리의 다른 글
| 22.12.02)CS특강과후발대1일차를 배운 25일차 (0) | 2022.12.02 |
|---|---|
| 22.12.01)this -call apply,callback, dom을 배운 24일차 (1) | 2022.12.01 |
| 22.11.29)js 데이터타입과 실행컨텍스트를 배운 22일차 (1) | 2022.11.29 |
| 22.11.28)팀플이 끝난 21일차 (0) | 2022.11.28 |
| 22.11.25)팀플 마무리 작업한 20일차 (0) | 2022.11.25 |