JS/Javascript

[Javascript] 화살표 함수(Arrow Function)

ui-o 2023. 2. 25. 16:16
반응형

화살표 함수

  • ES6(ES2015)부터 추가된 자바스크립트 함수 표현식의 간결한 문법
  • function 키워드 대신 => 기호를 사용하여 짧고 직관적으로 함수 작성 가능
  • this 바인딩 주의
  • new 연산자로 인스턴스 생성 불가, new 생성자와 함께 호출할 수 없음

특징

1. this 바인딩이 없음 → 상위 스코프의 this를 사용함

  • 기본 함수와 차이
    • 일반 함수는 호출될 때마다 this가 그 함수에 맞게 새로 정해지는 반면 (동적 바인딩)
    • 화살표 함수는 this를 자기 내부에서 새로 만들지 않고, "바깥쪽 함수" 또는 "바깥 스코프"의 this를 그대로 사용
  • 언제 유용? 콜백 안에서 this 유지할 때!

화살표 함수의 this 특징

  • 화살표 함수는 this를 만들지 않는다.
    → 자기 안에서 새로 바인딩하지 않음
  • this는 바깥(선언된 위치)의 this를 그대로 사용한다.
    → 스코프 체인을 따라 올라감
  • 객체 안에서 써도 객체를 가리키지 않는다.
    → 객체의 메서드로 사용하면 this는 window(전역) 일 수 있음
  • 전역에서 선언되면 this는 window가 된다.
    → 브라우저 기준
  • 그래서 객체의 속성을 참조할 때는 화살표 함수를 쓰면 안 될 수도 있다.

선언 위치에 따른 this가 가리키는 대상

✓ “화살표 함수는 this를 직접 만들지 않고, 자기가 태어난 환경의 this를 그대로 따라간다!”

1. 전역에서 선언 → window 또는 global

  • 전역 스코프의 this는 브라우저에선 window를 가리킴. 
const sayHi = () => {
  console.log(this); // 브라우저: window, Node.js: global
};

sayHi();

2. 객체 안에서 화살표 함수 → this는 객체 ❌, 바깥 스코프 ✅

  • 객체 ❌ → 바깥 스코프(this)
  • 화살표 함수는 자기만의 this를 만들지 않음 (일반함수 자동으로 객체를 가리키지 않음)
    그래서 객체 안이라고 해도, 화살표 함수의 this는 객체를 가리키지 않고 밖에서 물려받은 this를 그대로 씀
  • 화살표 함수가 선언된 바깥 스코프의 this를 그대로 사용함
    - 만약 바깥 스코프가 전역이라면 this는 window가 됨 (브라우저 기준)
const user = {
  name: "ho",
  sayHi: () => {
    console.log(this.name); // undefined
  }
};

user.sayHi(); // ❌ this는 user가 아님!

 

3. 함수 내부에 선언된 화살표 함수 → 바깥 함수의 this를 그대로 사용

  • 함수의 this를 그대로 따름
  • 함수 안에서 화살표 함수를 만들면, → 그 바깥 함수의 this를 그대로 따라감
  • 바깥 함수가 어떤 객체의 메서드로 호출됐다면 → 화살표 함수 안의 this도 그 객체를 가리킴
  • 이 덕분에 setTimeout, forEach 같은 콜백 안에서도→ this가 변하지 않고 유지됨
/*
여기서 this는 sayHi 함수의 this, 즉 user
화살표 함수는 그걸 그대로 가져다 씀
*/
const user = {
  name: "ho",
  sayHi: function () {
    const inner = () => {
      console.log(this.name); // ✅ "ho" 
    };
    
    inner();
  }
};

user.sayHi(); // "ho"

2. arguments 객체가 없음

  • 일반 함수는 함수 내부에서 arguments라는 유사 배열 객체를 사용할 수 있어, 전달된 모든 인수를 사용할 수 있음
  • 화살표 함수는 자기만의 arguments가 없음 → 대신 바깥쪽 함수의 arguments를 참조
  • 그래서, 만약 화살표 함수가 전역이나 함수 밖에서 쓰이면, 
    →  arguments가 없거나, 접근할 수 없어서 에러가 나거나 의도한 대로 실행되지 않을 수 있음

“ 화살표 함수 안에서 arguments를 쓰면, 자기 것 말고 바깥 함수의 arguments를 대신 사용!

function normalFunc() {
  const arrow = () => {
    console.log(arguments); // ✅ normalFunc의 arguments
  };
  arrow(1, 2, 3);
}

normalFunc("a", "b"); // arguments는 ["a", "b"] 

// 시각적 흐름
normalFunc("a", "b")
│
├─ arguments → ["a", "b"]
│
└─ arrow(1, 2, 3)
     │
     └─ 화살표 함수라 자기 arguments x
        → normalFunc의 arguments 사용 o

/* 
- 단계별 설명- 
1. normalFunc("a", "b")를 호출함
  → 이 함수의 arguments는 ["a", "b"]

2. 함수 안에 화살표 함수 arrow가 있음
  → arrow(1, 2, 3)처럼 3개의 인수를 넘겨 호출했지만…

3. 화살표 함수는 자기만의 arguments를 만들지 않기 때문에,
  → arrow() 안에서 arguments를 쓰면
  → 자기를 감싸고 있는 normalFunc의 arguments, 즉 ["a", "b"]가 출력됨

4. 그래서 결과는 ["a", "b"]가 출력 
  → console 출력 결과 Arguments(2) 0: "a", 1:"b"
  → arrow()에 넘긴 1, 2, 3은 무시됨
*/

 

3. new 키워드로 사용할 수 없음 (생성자 함수 ❌)

  • 일반 함수는 new로 객체를 생성할 수 있지만,
  • 화살표 함수는 생성자 함수가 아니므로 new로 호출하면 에러
  • 생성자 역할이 필요하다면 function 또는 class를 써야 함
const Person = (name) => {
  this.name = name;
};

const p = new Person("hp"); // ❌ TypeError

4. prototype 속성이 없음

  • 일반 함수는 prototype 속성을 가지며, 이를 기반으로 상속이 가능
  • 화살표 함수는 prototype 속성이 없음 프로토타입 기반 객체 생성이나 상속 불가

5. 익명 함수 로만 사용됨

  • 화살표 함수는 항상 변수에 할당하거나, 콜백으로 전달해서 사용해야 함
const add = (a, b) => a + b;
[1, 2, 3].forEach(v => console.log(v));

문법

  • 화살표 함수 정의가 한 줄인 경우 :  {} 와 return 생략 가능
  • 파라미터가 1개인 경우 : () 생략 가능
  • 객체 리턴할 때 주의 : 객체를 바로 리턴하려면 소괄호로 감싸야함
// 기본 문법
const 함수이름 = (매개변수) => {
  실행할 코드;
  return 결과값;
};


// 한 줄일때 표현 ({}와 return 생략 가능)
const func = (a) => a+2

// 파라미터(매개변수)가 1개 인 경우 () 생략 가능
const func = a => ()

// 다른 선언 방법
const func = x => y => z => `${x], ${y}, ${z}`
// 위 함수를 일반 함수로 표현하면 아래와 같음
function func(x){
	return function(y){
    	return function(z){
        	return `${x], ${y}, ${z}`
        }
    }
}
func(2)(4)(8)




// (key,value) object 반환 시 소괄호 사용
let get = param => ({sport:'soccer'})

// bool
(매개변수) => {
} bool 표현식 || boolean 값이 거짓을 떄 실행할 문장

화살표 함수와 일반함수의 차이

항목 화살표 함수 일반함수
this 바인딩 ❌ 없음 (상위 스코프를 사용함) ✅ 함수 내부에서 바인딩됨
생성자 함수 사용 ❌ 불가능 ✅ 가능 (new 사용 가능)
arguments 객체 사용 ❌ 불가능 ✅ 가능
간결한 문법 ✅ 매우 간결 ❌ 다소 장황함

 

구분 화살표 함수 일반 함수
this 외부 스코프 상속
- 자신이 this를 가지지 않음 
  자신이 정의 된 외부 스코프의 this를 그대로 사용
- this를 묶는 것이 가능
- property에 화살표 함수를 연결하면 화살표 함수 블록에서
 this가 인스턴스를 참조하지 못함
- 내부 콜백에서 this가 바뀌는 문제를 피하고 싶을때, 화살표 함수를 사용 
호출 방식에 따라 결정

호출된 문맥에 따라 "this"가 바뀜
arguments 사용 불가 사용 가능
생성자 (new) 불가능 가능
메서드 정의에 적합
const box = document.querySelector('.box')

// 일반함수에서 this
box.addEventListener('click', function(){
	this.style.color="red" // box를 가리킴
})
// 화살표 함수에서 this
/*
 - 화살표 함수는 자신만의 this를 가지지 않음
 - 대신 함수가 정의된 시점의 this(상위 스코프의 this) 를 그대로 상속받음
 - 해당 this의 상위스코피는 window(브라우저 전역 객체)
*/
box.addEventListener("click", ()=>{
	this.style.color='red' // this가 Window 객체로 설정되어 property ~~ undefined 에러 발생
})


// 화살표 this의 적절한 활용
/*
- 여기서 addEventListener는 일반함수로 등록되어 this는 box를 가리킴
- setTimeout 함수를 화살표 홤수로 사용하여 외부의 this를 그대로 가져옴 
  (※setTimeout은 비동기적으로 실행되는 함수이기 때문에
   여기서 setTimeout(function(){..} 처럼 일반함수를 사용했다면, this는 window를 가리킴
   
   !" 내부 콜백에서 this가 바뀌는 문제를 피하고 싶을때, 화살표 함수를 사용 "
   
   function()은 this를 "호출하는 방식"에 따라 정함
   - 첫 번째 function()은 addEventListener가 box 기준으로 호출해줌
     → 그래서 this === box
    - 두 번째 function()은 1초 뒤에 setTimeout이 직접 호출
     → 이때 **일반 함수는 전역 객체(window)**를 this로 바꿈
     → 따라서 this === window
   - setTimeout(함수, 시간)은 1초 뒤에 함수만 따로 전역 컨텍스트에서 호출함
   - 이때 일반 함수는 주변 문맥을 기억하지 못하고, 자기만의 this를 다시 설정해버림 → window

  
*/
box.addEventListener("click", function () {
	this.style.color = "red";
	setTimeout(() => { 
		this.style.color = "black"; // 이 this는 상위스코프에 상속되어 box를 가리켜 정상 작동
	}, 1000);
});

 

 

[javascipt] 일반함수와 화살표 함수에서의 this

화살표 함수와 일반함수의 this 비교일반 함수는 호출 방식에 따라 this가 달라짐.화살표 함수는 정의된 위치의 this를 그대로 가짐.따라서 화살표 함수는 보통 this를 고정해서 사용하고 싶을 때 사

u-pub.tistory.com

 


화살표 함수에서  arguments

  • arguments 객체는 함수 내부에서 접근할 수 있는 배열 객체로 해당 함수에 전달돼 인수의 값을 담고 있음
  • 일반함수에서 arguments는 배열 표기법을 사용하여 해당 인수에 접근 가능
  • 화살표 함수에서 arguments는 스프레드 문법을 활용하여 해당 인수에 접근 가능

 

// 일반함수의 arguments 활용
function test(){
	 console.log(arguments[0])
 }
test(1,2) // => 1

// 화살표 함수의 arguments의 잘못된 사용
const show=()=>{
	const name = arguments[0]
	console.log(`name : ${name}`)
}
show('j','a','b') // 오류 :arguments is not defined 

// 화살표 함수의 arguments 적절한 사용(스프레드 문법 활용)
const show2 = (...args) => {
	const name = args[0]
	console.log(`name : ${name}`)
}
show2('a','b','c') // name:a

 

반응형