🐱 함수 표현식 이론
🐶 함수 표현식
// 함수 선언문
function sayHi()
// 함수 표현식
let sayHi = function() {
alert( "Hello" );
};
함수 표현식은 함수를 생성하고 생성한 함수를 변수에 할당하는 형태이다.
→ 함수는 “값”이라서 변수에 할당할 수 있다.
sayHi() → 함수를 실행한 값을 반환한다.
sayHi → 함수를 실행하지 않고 함수 본문이 출력된다.
const a = sayHi() ⇒ a에 sayHi()의 반환값 ‘hello’가 담긴다.
const b = sayHi ⇒ b는 sayHi 함수(function) 본문이 담긴다.
a는 저장된 값을 가져올 수 있지만 b는 함수 본문이 들어가 있어서 sayHi()처럼 b를 함수처럼 실행할 수 있다. b()
🐶 함수의 복사
함수 선언문으로 작성해보기
function sayHi() { // (1) 함수 생성
alert( "Hello" );
}
**let func = sayHi;** // (2) 함수 복사 -> 함수 본문 그대로 넘긴다.
func(); // Hello // (3) 복사한 함수를 실행한다.
sayHi(); // Hello // 본래 함수도 정상적으로 실행됩니다.
let func = sayHi; -> sayHi 함수의 본문을 그대로 복사한다.
함수 표현식으로 작성해보기
let sayHi = function() {
alert( "Hello" );
};
**let func = sayHi;** // let func = sayHi() 괄호해야 alert가 실행된다.
함수 표현식은 세미콜론을 붙여야 한다.
⇒ ‘문’과 ‘식’의 차이 : 문은 세미콜론을 안붙여도 되지만 식은 세미콜론을 붙여줘야 한다.
🐶 콜백 함수
callback 함수 : 함수 본문이 먼저 넘어가고, 이후에 함수 안에서 나중에 실행되는 것. 함수를 함수의 인수로 전달하고, 필요하다면 인수로 전달한 함수를 나중에 호출한다.
➡️ 함수를 값처럼 전달한다.
ask("동의하십니까?", showOk, showCancel); → 인수에 showOk, showCancel 함수 자체를 전달해서 ask 함수의 인자에는 함수가 그대로 들어가게 된다.
➡️ 함수 결과값이 아닌 함수 본문이 그대로 들어가는것!!
function ask(question, yes, no) { → ask 함수의 인자 yes, no에 각각 인수에 전달한 showOk, showCancel 함수가 본문 그대로 들어가게 된다.
if (confirm(question)) yes() else no(); → question에 글자가 들어가 있으면 yes함수(showOk)를 실행하고, 아니면 no(showCancel)함수를 실행한다.
⇒ 함수가 값처럼 취급되기 때문에 가능한 것
⬇️ 함수표현식으로 간단하게 쓰기
→ 함수를 실행할 때 값으로 함수 본문을 통째로 바로 전달한다.
⚠️ 이 때 argument 순서 바뀌면 안된다!!!!
⛅ 변수에 할당한 것처럼 안보이는데 왜 함수 표현식이야?
⛅ 변수에 할당한 것처럼 안보이는데 왜 함수 표현식이야?
➡️ 아래 function() 2개가 callback 함수이고,
그 callback 함수들이 위에 ask 함수에서 yes, no에 할당되는 것임! 할당되고 실행이 나중에 되는 것.
딱 보기에 변수에 할당된 것처럼 아니라고 함수 표현식 아니라고 하지 말 것.
🐶 익명 함수(Anonymous function)
이름 없이 선언한 함수
→ 변수에 할당된 게 아니라 함수 밖에서는 접근할 수 없다.
변수 자체를 함수의 이름으로 쓰는 경우가 많음
➡️ 콜백 함수에서 주로 사용한다.
// 익명 함수
let anonymousFunctionExpression = function(){};
// 유명 함수 : 이름이 존재하는 함수
let namedFunctionExpression = function hello(){
};
→ 변수에 할당된 게 아니라 함수 밖에서는 접근할 수 없다.
🐶 함수 선언문, 함수 표현식 차이점
- ❓ 함수 선언문과 함수 표현식 중 무엇을 선택해야 하나요?함수 선언문을 사용하면 가독성도 좋아집니다. 코드에서 let f = function(…) {…}보다 function f(…) {…} 을 찾는 게 더 쉽죠. 함수 선언 방식이 더 “눈길을 사로잡습니다”.
- 그러나 어떤 이유로 함수 선언 방식이 적합하지 않거나, (위 예제와 같이) 조건에 따라 함수를 선언해야 한다면 함수 표현식을 사용해야 합니다.
- 제 경험에 따르면 함수 선언문을 이용해 함수를 선언하는 걸 먼저 고려하는 게 좋습니다. 함수 선언문으로 함수를 정의하면, 함수가 선언되기 전에 호출할 수 있어서 코드 구성을 좀 더 자유롭게 할 수 있습니다.
🐔 차이점
- 문법 차이
함수 선언문 ⇒ function 키워드 + 중괄호 형태
➡️ 선언 전에 호출할 수 있어서 가독성이 좋고 코드 구성이 비교적 자유롭다.
// 함수 선언문
function sum(a, b) {
return a + b;
}
함수 표현식 ****⇒ 함수를 생성하고 함수를 변수에 할당하는 형태
➡️ 콜백 함수에서 많이 사용한다(주로 Arrow function으로 사용한다.)
// 함수 표현식
let sum = function(a, b) { // 함수를 생성해서 변수에 할당한다.
return a + b;
};
➡️ 함수 선언문은 지양 해야 한다 .. 협업을 하기 때문에
2. 미리 호출해서 쓸 수 있음(선언문) vs 선언 이후에 쓸 수 있음(표현식)
함수 선언문 → 함수 본문 전체가 올라간다. 따라서 함수를 호출하면 정상적으로 실행된다.
함수 표현식 → 선언한 변수만 올라간다. 값이 할당되기 전까지는 TDZ에 들어가기 때문에 let, const로 선언된 변수들은 할당하기 전까지는 절대 사용할 수 없다. 올라간 변수에는 아직 값이 할당되지 않은 상태이기 때문에 에러가 발생한다.
⚠️ 함수를 선언하기 전에 호출해서 쓰는 건 bad case이긴 함. 권장하지 않음.
🧻 sum2를 let이 아닌 var로 선언해서 호이스팅하면 안돼?
➡️ var은 호이스팅 하면 최초값이 undefined가 돼서 sum2가 undefined로 선언된다.
undefined를 호출하면 에러가 발생한다.
3. 스코프의 영역이 다르다
함수 선언문 → 함수가 선언된 블록 안에서만 어디서 선언하든 실행할 수 있다. 블록 밖에서 함수 선언문을 찾으려고 하면 스코프가 블록 안을 벗어나지 못해 에러가 발생한다.
➡️ 전체가 호이스팅된다.(lexical environment)
함수 표현식 → 할당을 나중에 함수 안에서 하기 때문에 블록 밖에서도 함수를 호출할 수 있다.
➡️ 지정된 변수 값(sum)만 올라감
➡️ 할당되기 전까지는 TDZ에 들어가 있는 상태이기 때문에 호출하면 에러가 발생한다.
함수선언문
sum(1,2) // 실행 잘됨
// 함수를 생성해서 변수에 할당한다.
function sum(a, b) {
return a + b;
};
함수표현식
sum(1,2) // error
let sum = function(a, b) { // 함수를 생성해서 변수에 할당한다.
return a + b;
};
sum(1,2) // 실행 잘됨
let 선언 부분은 호이스팅이 됨 → TDZ 로 이동 → 할당하기 전까지 TDZ에 머무름 → 호출 불가능(할당돼서 TDZ에 나오면 호출 가능)
선언문 표현식
선언문 | 표현식 | |
변수 선언 | 실행 | error |
🐶 요약
- 함수는 값입니다. 따라서 함수도 값처럼 할당, 복사, 선언할 수 있습니다.
- “함수 선언(문)” 방식으로 함수를 생성하면, 함수가 독립된 구문 형태로 존재하게 됩니다.(함수 본문이 통채로 들어간다. )
- “함수 표현식” 방식으로 함수를 생성하면, 함수가 표현식의 일부로 존재하게 됩니다.(어딘가에 값이 들어가서 할당 받은 형태이다.)
- 함수 선언문은 코드 블록이 실행되기도 전에 처리됩니다. 따라서 블록 내 어디서든 활용 가능합니다.(제일 위로 올라가서 그 아래에서 함수라는 값을 이미 가지게 된다.) ⇒ 권장x
- 함수 표현식은 실행 흐름이 표현식에 다다랐을 때 만들어집니다.(let 키워드가 위로 올라가고 나중에 할당부를 만나야 그때 실행할 수 있다.)
⇒ 함수를 위에 선언하고 나중에 호출하는 방식 쓰는걸 권장한다. (선언문 방식 권장 안함)
🐱 함수 표현식 실습
🐶 arguments (⇒ rest parameter 와 유사함)
(함수가 만들어준) 함수 안에서만 접근 가능한 인수들의 집합 객체로, 배열과 유사한 형태로 유사배열이다. (유사배열이기 때문에 배열의 메서드를 가져다 쓸 수 없다.) 인수(argument)에 값이 많이 들어갈 때 한 번에 받아서 사용한다. 인수 arguement는 함수 안으로 들어가면 매개변수로 사용 가능 하다
🗣️ 그 인수들 내가 한 번에 관리할 수 있게 arguments 만들어서 안에 넣어줄게~
⭐ 함수 선언문, 함수 표현식 둘 다 arguments를 가진다!! (화살표 함수는 ❌)
🐶 총합(total) 구하기 예제
🐔 for문
// ! 1. 함수 선언문을 함수 표현식을 만들어보기
// 함수 선언 → 일반 함수 (표현)식
let calculateTotal = function (){
console.log(arguments); // 없어도 상관없음
//함수 안에서만 접근 가능한 인수들의 집합 객체로서 배열과 유사한 형태를 가지고 있는 것은 ? : arguments
// arguments 객체를 사용해 함수의 매개변수 없이 아이템 총합 구하기
let total = 0;
for(let i = 0; i < arguments.length; i++){
total += arguments[i];
}
return total
};
const result = calculateTotal(1000, 500, 200, 6500, 100)
console.log(result);
→ arguments 객체를 사용해 함수의 매개변수 없이 아이템 총합을 구했다
가지고 있는 값들을 arguments가 유사배열로 만들어서 length보다 짧으면 total에 값을 처음부터 순서대로 넣어서 총합을 구한다.
🐔 for..of
let calculateTotal = function (){
let total = 0;
// 사용자 지정명
for(let value of arguments){
//console.log(value); // 1000 500 200 6500 100
total += value;
}
return total
};
for..of 문으로 arguments에서 value 값을 하나씩 뽑으면서 total에 값을 더한다.
🐔 call 함수로 forEach 빌려 쓰기
let calculateTotal = function (){
let total = 0;
// * 3. forEach 빌려쓰기
// arguments가 배열이 아니기 때문에 forEach로 돌릴 수 없다.
// arguments.forEach(item)=>{
// console.log(item);
// }
//Array 능력중 forEach문을 arguments가 빌려쓰고 값은 함수가 들어간다. => 아이템 순환 처리
Array.prototype.forEach.call(arguments, function(item){
//console.log(item); // 1000 500 200 6500 100
total += item;
})
return total
};
Array.prototype.forEach.call : arguments는 배열이 아닌 유사배열이기 때문에 배열의 메서드를 사용할 수 없다. 따라서 arguments는 call 함수를 통해 Array의 능력인 forEach문을 빌려 써서 순환하면서 item 값을 total에 넣는다.
⚠️ forEach문은 배열만 사용 가능하다는 점 알아두기! 유사배열은 안됨
🐔 Array의 slice를 빌려 써서 진짜 배열로 만들기(원래는 유사배열), forEach (forEach는 인스턴스 메서드)
// * 4. Array의 힘을 빌리기
// arguments인 유사배열을 진짜 배열로 만듦
// 찐 배열이 가지고 있는 능력 중 유사배열인 arguments가 slice를 빌려써서
// 값을 도려내서 배열에 집어넣어 진짜 배열로 만든다.
// => 진짜 배열이 됐으므로 배열의 능력을 다 사용할 수 있음(push, pop, reduce..)
// Array의 slice 기능으로 arguments 유사 배열을 진짜 배열로 만들고 realArray에 집어넣는다.
let realArray = Array.prototype.slice.call(arguments)
// Arr.slice() 배열로 반환
console.log(realArray);
realArray.forEach(function(item){
total += item; // 콜백함수의 body(내용)
})
return total;
};
arguments가 Array의 slice 기능을 call 함수를 통해 빌려서 값들을 도려내고 도려낸 값들을 배열에 집어넣어 진짜 배열로 만든다. 그리고그 값들을 realArray에 집어넣는다. (⇒ 유사배열을 진짜배열로 만든다.)
➡️ 배열 형태로 바꿔줬기 때문에 forEach문을 쓸 수 있게 된 것!
⚠️ 위 코드에서 function(item)이 콜백함수! forEach는 콜백함수를 반복한다.
- 🐱 Instance Method, Static Method
Instance Method(인스턴스 메소드) ⇒ 객체를 생성한 이후에 호출이 가능하다.
Static Method(정적 메소드) ⇒ 객체를 생성하지 않고 클래스명.메서드명으로 호출이 가능하다. (ex. Object.entries())
🐔 Array.from 사용해 배열로 만들기 → Static 메서드
// * 5. Array.from()
let realArray = Array.from(arguments);
console.log(realArray);
realArray.forEach(function (item) {
total += item;
})
// Object.prototype.toString()
// Object.entries()
return total;
};
Array.from → 배열이 가지는, 배열로 만들어줄 수 있는 static 메서드
Array.from을 사용하면 프로토타입에 접근할 필요도 없고, call 메소 사용할 필요 없이 대상을 배열로 반환해준다.
⛅ 인스턴스 메서드 → 프로토타입 메서드(.붙여서 자동 코드 뜨면 되고 아니면 안됨) 유틸 메서드 → static 메서드
💡 정적 메서드 (static 메서드) 종류 검색 해볼 것
🐔 spread syntax(spread operator) 활용해 배열로 만들기
// * 6. spread syntax (spread operator) 이용 : 배열 만드는 방법
// 가장 많이 쓰임(최신이기도 함)
// ? => 장점 : 배열 합성이 편함
// let arr = [10, 50, 100];
//let realArray = [...arguments, ...arr]; => arguments랑 기존 arr랑 합쳐짐
let arr = [10, 50, 100];
let realArray = [...arguments];
console.log(realArray);
realArray.forEach(function(item,index){
total += item;
})
return total;
};
→ 배열 안에 담긴 내용을 풀어서 쓴다.
spread syntax의 장점 : 배열 합성이 편하다. ⇒ […arguments, …arr]
최신 방법이기도 하고 가장 많이 쓰인다.
🐔 array.reduce() → 원하는 값 뽑아내기
let arr = [10, 50, 100];
let realArray = [...arguments];
return realArray.reduce((acc, item)=>{
return acc + item
}, 0) // 0 => initValue
// 화살표 함수 활용해 이렇게 줄일 수 있다.
return realArray.reduce((acc, item)=> acc + item, 0)
reduce(acc, item) ⇒ acc : 누적값 / item : 순회하는 아이템들
return acc + item ⇒ 누적값 + 가리키는 값 / 누적값에 아이템들을 하나씩 넣으면서 총합 구하는 방식
initValue : 최초값을 설정해줘야 한다. (return의 끝에 들어감) 0이 아닌 값을 최초값으로 지정할거면 무조건 넣어줘야 한다. 까먹지 말기!!
🐶 익명 함수 표현식(이름없는 함수 표현식)
→ 기본 표현식 형태
// 익명(이름이 없는) 함수 (표현)식
// console.dir(anonymousFunctionExpression) => 함수 자체 던지면 함수가 튀어나온다.
// dir은 안의 내용을 조회한다. 뭘 갖고 있는지
let anonymousFunctionExpression = function(){
};
익명 함수를 넣었지만 함수 이름으로 조회 함수지만, 객체로 쓸 수 있음. 함수는 객체로부터 만들어졌기 때문에. callback 함수 인수에 바로 쓸 때 많이 사용한다.
- dir : 뭘 갖고 있는지 안의 내용을 조회한다.
🐶 유명 함수
이름을 가진 함수 표현식으로 선언도 같이 한다.
// 유명(이름을 가진) 함수 (표현)식
let namedFunctionExpression = function hello(){ // hello()
};
함수라는 객체에 hello라는 name을 부여한 것이다.
이 함수 객체를 호출하려면 namedFunctionExpression()으로 호출해야한다.
.name을 사용해 함수의 이름 hello를 바로 불러올 수도 있다.
함수도 객체라서 .key를 사용할 수 있다.
🐶 콜백 함수 ⇒ 흐름 알기 ⭐⭐⭐⭐
→ 부모 함수에 인수를 많이 쓴다.
// 콜백 함수 (표현)식
// 매개변수에 callback을 받음
// 정의
let callbackFunctionExpression = function(isActive, callback){
// 내부적으로 이렇게 실행됨 => callback() = function(){console.log('콜백 함수 실행!');
// callback();
if(isActive){
callback(); // 조건을 따진 이후 함수 실행하거나 실행안함 => 콜백함수(나중에 실행됨)
}
};
// 호출
callbackFunctionExpression(
true,
// 첫 번째 인수로 함수 본문을 넘김 (함수 body가 통째로 전달됨)
function(){
console.log('콜백 함수 실행!');
}
);
a(callback1,callback2)
// 콜백은 내부에서 실행되어야 한다.(ex:handleFontSizeDecrease()x)
minus.addEventListener("click", handleFontSizeDecrease);
위 함수에서 주석처리된 **callback()**은 내부적으로 callback() = function(){console.log('콜백 함수 실행!'); 처럼 실행된다.
⚠️ 콜백 함수는 내부에서 실행되어야 한다!!
⬇️ 예제 (원하는 홈페이지 주소로 이동하는 함수 (movePage))
const movePage = function(url,success,fail){
if(url.match(/http.+www/) && typeof url === 'string'){
success(url)
}else{
fail()
}
}
movePage(
'www.naver.com',
function(url){
console.log('성공 몇초 뒤 해당 페이지로 이동합니다.');
setTimeout(() => {
window.location.href = url
}, 3000);
},
function(){
console.log('올바르지 않은 주소입니다.');
// ????
}
)
🐶 즉시 실행 함수 표현식
즉시 실행 함수(IIFE, Immediately Invoked Function Expression)) : 함수를 생성함과 동시에 즉시 실행한다.
나온 이유 → 변수의 보호를 위해 탄생했다. (캡슐화, 은닉화)
형태 : 소괄호로 함수를 감싼다.
(function () {
statements
})();
➡️ 즉시 실행 함수에 익명 함수를 사용하는 이유 : 즉시 실행 함수는 선언과 동시에 호출되어 재사용이 불가능하기 때문에 함수에 굳이 이름을 지어줄 필요가 없다.
let IIFE;
// 함수 스코프 형성됨
(function(){
var x = 10;
console.log('즉시 함수!');
})() // 호출부
// console.log(x); => x는 함수 스코프 안에 갇혀 밖에서 접근할 수 없다.
// (캡슐화, 은닉화 => 변수 보호)
// 이거 무슨 예제임,,,
const MASTER = (function (){
var x = 10;
console.log('즉시 함수!');
return '퉤';
//return {}; => 객체 내보냄
})()
console.log(MASTER);
console.log(MASTER.setKey('새로운 비밀번호'));
🐶 클로저(Closure)
내부 함수와 외부 스코프의 변수를 잇는 연결고리. 의도적으로 함수가 특정 스코프에 접근할 수 있도록 정의하는 경우
let a;
{
let b = 1;
a = function(){
console.log(b);
}
}
a(); // 1
🐱 화살표 함수(Arrow Function)
화살표 함수 : 함수 표현식에 포함되고, 함수 표현식을 간결하게 쓸 수 있다.
화살표 함수의 기본 형태
일반 함수 표현식 ⇒ 변수 = function(){}
화살표 함수 ⇒ 변수 = () ⇒ {}
// 일반 함수
let func = function(arg1, arg2, ...argN) {
return expression;
};
// 화살표 함수
let func = (arg1, arg2, ...argN) => expression
예시
let sum = (a, b) => { return a + b };
let sum = (a) => ( a + b );
let sum = a => a + b;
/* 위 화살표 함수는 아래 함수의 축약 버전입니다.
let sum = function(a, b) {
return a + b;
};
*/
alert( sum(1, 2) ); // 3
화살표 함수는 중괄호로 열고 닫으면 return 키워드를 넣어서 사용할 수 있다.
중괄호 없으면 return 생략해도 됨
중괄호 생략 ⇒ 알아서 값 return 하는 것을 내포한다.
화살표 함수의 특징
- 중괄호 있으면 undefined를 리턴하므로 return 지시자를 써줘야 한다.
- 함수 본문이 한 줄인 함수일 땐 화살표 함수를 쓰는게 좋다.
- 중괄호 없이 작성하면 그 자체로 return 기능을 가지기 때문에 return 지시자를 쓰지 않아도 된다.
- 인수가 한 개이면 괄호를 생략할 수 있다. (두 개 이상은 써줘야 한다.)
let sum = (a, b) => { return a + b };
// 일반 함수
let func = function(arg1, arg2, ...argN) {
return expression;
};
// 화살표 함수
let func = (arg1, arg2, ...argN) => expression
🐱 화살표 함수 실습
🐶 rest parameter ⇒ arguments와 유사
함수 표현식은 arguments가 있지만 arrow function은 arguments가 없다.
arrow function 안에서만 사용할 수 있는 arguments 같은 애 ⇒ rest parameter(나머지 매개변수)
rest parameter : ...args, ...rest, ...children (이름은 짓기 나름)
let calcAllMoney = (...args)=>{ //rest parameter
let total = 0;
args.forEach((item)=>{
total += item;
})
return total;
};
(...args)=>{ ⇒ args의 모든 값을 받아서 배열로 만들어준다.
밖에서 …를 쓰면 spread syntax로 인식하고, 매개변수에서 쓰면 rest parameter로 인식한다.
rest parameter는 나머지 값만 가져올 수 있다.
ex) (a, b, …args) ⇒ args에는 a, b를 뺀 나머지 값만 나오게 된다.
나머지 : args
→ a, b에 들어갈 1000, 500을 제외한 200과 2000이 …args에 들어가 200, 2000만 반환된다.
🐔 …args 예시 + 화살표 함수로 작성해보기
let calcAllMoney = (a, b, ...args)=>{
return args.reduce(function(acc, item){
return acc + item; // 2200
}, 0)
// ⬆️ 화살표 함수로 쓰기
// reduce의 콜백 함수에서 acc + item 값을 내뱉는다.
return args.reduce((acc, item)=>acc + item, 0) // 2200
};
🐶 함수 만드는 방법 3가지(차이점)
🐔 형태
// 1. 함수 선언문
function normalFunction(){
console.log(this);
}
// 2. 함수 표현식
const expressionFunction = function(){
console.log(this);
}
// 3. 화살표 함수식
const arrowFunction = ()=>{
console.log(this);
}
- 함수 선언문
2. 함수 표현식
3. 화살표 함수식
arguments : (…) 생성자 x , 함수로써의 기능만 수행함 (가벼움, 빠르게 실행됨)
🪗 함수 선언문과 함수 표현식은 prototype: {constructor: *f*} 로 정의되어 있지만 화살표 함수식은 정의되어 있지 않다.
⇒ **화살표 함수는 생성자(Constructor)를 내장하고 있지 않다는 뜻
화살표 함수는 생성자로서의 기능을 제외하고 함수로서의 기능만을 사용하기 위해 나온 함수이다.
Cunstructor를 내장하지 않아서 가볍고 속도가 훨씬 빠르다.
❓ 생성자가 뭔데???⇒ 객체 생성할 때 사용하는 메소드
const obj = new Object() ⇒** Object() 객체를 생성해서 해당 객체의 주소를 obj에 넣는다.
🪗 console 창에 dir(normalFunction) 형식으로 찍어 차이점을 찾아보았다.
⇒ 함수선언문, 함수표현식과 다르게 화살표함수식 arrowfunction 은
constructor ( 생성자 )를 내장하고 있지 않다.
생성자로써의 기능을 제외하고 진짜 함수로써의 기능만 수행하기 위해서.
constructor 을 내장하면 부모의 부모의 등등 기능을 상속받아야하기 때문에 굉장이 무거움.
🐶 함수의 양면의 얼굴(두 가지 기능)
const Button = ()=>{
}
const a = Button()
const b = new Button()
const a = Button() → Button 함수의 리턴값이 a에 할당된다. 리턴값이 없으면 undefined를 반환한다.
const b = new Button() → Button() 객체를 생성해서 해당 객체의 주소를 b에 저장한다.
⇒ 일반 함수와 함수 표현식에서 Constructor 기능을 하는 것이 new 이다.
const c = new String(’a’) ⇒ 문자열 ‘a’를 담고 있는 String 객체를 생성한다. 그리고 해당 객체의 주소를 c에 저장한다.
🐱 두 가지 기능 분리시키기 위해 나온게 화살표 함수이다!!
🐱 this
함수를 만들어서 실행하면 함수 자체도 실행 컨텍스트가 생겨서 그 안에서 환경이 구성된다. 누구는 변수로, 누구는 함수로 지정이 되는 과정을 거친다. 그 과정중에 this라는 애가 바인딩 된다.(묶인다.) this는 변수로 정의하지 않아도 예약어처럼 언제 어디서든 쓸 수 있음. 함수 안에서 this를 찾는 방법은 일반 함수, 화살표 함수에 따라 다름.
일반함수 → 나를 호출한 대상이 this로 들어간다.
화살표 함수 → this를 찾지 않는다. this를 바인딩하지 않기 때문에 부모꺼를 찾아서 가져온다. : 바깥 실행 컨텍스트에 있는 this를 가져온다.
🐱 함수 선언문, 함수 표현식, 화살표 함수식 this
→ window (찐 객체) : 전역 객체
브라우저 : window / 노드 : global ⇒ 합해서 global this.
// * 함수 만드는 방법 3가지
// ? 1. 함수 선언문
function normalFunction(){
console.log(this); // window 객체가 나옴(찐객체)
}
window.normalFunction() // 일반 함수 -> 윈도우가 호출 시켜줌 => this : window
// ? 2. 함수 표현식 -> 전역 객체가 아니라서 걍 불러야함.
const expressionFunction = function(){
console.log(this);
}
expressionFunction(); // this => window
// 얘도 일반 함수 -> 윈도우가 호출해서 this는 window 가 담긴다.
// ? 3. 화살표 함수식 -> 함수로서의 일만 해서 가볍다.
const arrowFunction = ()=>{
console.log(this);
// window가 나오지만 window에 의해 호출된게 아니라 나 자신이 호출 된것.
// 여기서의 this는 다 this 없는데? 바인딩 안했는데? 내 부모꺼 누구야
// 부모는 선언된게 없어서 window(this)로 인식함. => 그래서 window를 가져오는 것.
}
→ 부모를 window로 인식한다.
let callbackFunctionExpression = function(callback){
callback();
};
한줄평
this를 찾아가는 과정에서 많은 어려움이 있었다. 앞으로의 많은 학습이 필요하다고 느껴진다
'👨💻회고 일기장 > 🙈멋쟁이사자처럼 회고' 카테고리의 다른 글
07-11 회고록 (9) | 2023.08.28 |
---|---|
07-07 회고록 (1) | 2023.08.21 |
07-06 회고록 (0) | 2023.08.07 |
07-05 회고록 (1) | 2023.07.13 |
23-07-04 회고록 (0) | 2023.07.07 |