자바스크립트의 화살표 함수와 `this` 함수: 완벽 가이드

  • 의 가치 this 자바스크립트에서 함수 호출 방식은 전역 컨텍스트, 객체 메서드, 엄격 모드 사용 여부에 따라 달라집니다.
  • 화살표 함수는 자체적으로 생성자를 만들지 않습니다. this대신, 이들은 정의된 도메인의 용어를 어휘적으로 상속받으므로 콜백에서 발생하는 많은 문제를 방지할 수 있습니다.
  • 콜백 함수와 배열 메서드에서는 화살표 함수를 사용하는 것이 좋지만, 객체 메서드, 생성자 또는 DOM 이벤트 핸들러에서는 화살표 함수 사용을 피하는 것이 좋습니다. this 동적.

자바스크립트에서 화살표와 이 함수의 작동 방식을 보여주는 그림입니다.

자바스크립트로 프로그래밍을 좀 해본 사람이라면 이 키워드를 분명히 알아볼 것입니다. 이것 때문에 당신은 한두 번 골머리를 앓았군요.그리고 ES6에서 화살표 함수가 등장하면서 상황은 더욱 복잡해졌습니다... 아니면 보는 관점에 따라 더 간단해졌다고 할 수도 있겠죠.

이 글에서는 그 작동 방식을 자세히 살펴보겠습니다. 이는 일반 함수와 화살표 함수 모두에 적용됩니다.화살표 함수가 어떤 때는 특정 객체를 가리키고 어떤 때는 전역 객체를 가리키는 이유는 무엇이며, 어떤 상황에서 화살표 함수를 사용하는 것이 적절하고 어떤 상황에서는 피하는 것이 더 나은가요?

정확히 무엇 this 자바스크립트에서

예약어 this 이는 실행 컨텍스트에 대한 참조입니다. 현재 실행 중인 함수의 상태를 결정합니다. 다른 언어와 달리 자바스크립트에서는 함수가 정의된 위치가 아니라 함수의 실행 상태를 기준으로 결정합니다. 호출하는 방법.

이는 동일한 함수를 여러 가지 방식으로 호출할 수 있으며, 각 방식에서, this 다른 물체를 가리킬 수 있습니다직접적인 업무 배정으로 바꿀 수 있는 게 아닙니다 (그럴 수 없어요). this = algo하지만 다음과 같은 특정 메커니즘을 통해 영향을 줄 수 있습니다. call, apply y bind.

게다가 그들의 행동은 서로 다릅니다. 엄격 모드와 비엄격 모드비엄격 모드에서 함수를 객체 없이 "bare"로 호출하면, this 일반적으로 브라우저에서 사용하는 전역 객체입니다. window엄격 모드에서는 가능하지만 undefined이러한 차이점은 서로 다른 출처의 코드 예제를 비교할 때 중요합니다.

이는 전역적인 맥락과 일반적인 기능에서 나타나는 현상입니다.

브라우저에서 모듈이나 함수 내부에 있지 않을 때 전역 컨텍스트는 객체입니다. window그리고 거기에 this 그 물체를 가리키세요즉, 콘솔에 다음을 입력하면 다음과 같습니다.

console.log(this === window); // true en un entorno de navegador no estricto

일반적인 방식으로 선언된 함수(일반 함수) 내부에서, this 그 함수의 이름이 무엇인지에 따라 다릅니다.사전 객체 없이 호출하는 경우, 즉 비엄격 모드에서는 this 일반적으로는 글로벌 버전이며, 엄밀히 말하면 그렇습니다. undefined그래서 코드를 한 사이트에서 다른 사이트로 옮길 때 종종 문제가 발생하기도 합니다. 이것은 더 이상 당신이 기대했던 것이 아닙니다..

이는 일반 함수로 정의된 객체 메서드에 있습니다.

기존 구문을 사용하여 객체에 메서드를 정의할 때, this 메서드 내부에서 객체 자체에 대한 참조 해당 메서드가 호출된 출처입니다.

예를 들어 다음과 같은 것이 있다면:

const obj = {
  speak() {
    console.log(this);
  }
};
obj.speak();

전화 obj.speak() 만든다 this 이내 speak 그 사람이 되어라 obj이는 사람들이 직관적으로 기대하는 동작입니다. 즉, 메서드가 객체를 "대신하여" 말하는 것입니다.

축약된 구문 대신 일반 함수를 사용하면 효과는 동일합니다. 핵심은 해당 메서드를 호출하는 방식에 있습니다.메서드 약어를 사용했는지 키워드를 사용했는지는 중요하지 않습니다. function 물체 내부에.

이는 화살표 함수로 정의된 메서드에 있습니다.

화살표 함수를 사용하여 메서드를 정의하면 상황이 달라집니다. 예를 들어 다음과 같습니다.

const obj2 = {
  speak: () => {
    console.log(this);
  }
};
obj2.speak();

이 경우, 실행할 때 obj2.speak() 당신은 그것을 볼 것입니다 this 더 이상 그렇지 않습니다 obj2하지만 외부 어휘적 맥락 해당 객체로 이동하는데, 일반적인 브라우저 스크립트에서는 대개 전역 객체입니다. window.

처음 보면 다소 당황스러울 수 있는데, 객체의 메서드가 객체 자체를 가리킬 것이라고 예상하기 때문입니다. 하지만 화살표 함수는 자체적으로 생성자를 만들지 않습니다. this그들은 가치를 물려받습니다. this 해당 클래스가 정의된 범위에 따라 결정됩니다. 해당 범위가 전역 범위이면 전역 범위를 상속받고, 다른 범위이면 해당 다른 범위를 상속받습니다.

따라서 현대 문서에서 자주 반복되는 권장 사항은 다음과 같습니다. 화살표 함수를 객체 메서드로 사용하지 마십시오. 필요할 때 this 저 목표물을 조준하세요.

어휘 범위 this 화살표 함수

일반 함수와 화살표 함수의 주요 차이점은 후자가 일반 함수보다 더 안전하다는 점입니다. 어휘적 링크를 가지고 있습니다 this간단히 말해서, 그들은 스스로 결정하지 않습니다. this 그들이 서로 전화할 때가 아니라, 그들이 창조하다.

다음 예를 생각해 보세요.

const obj3 = {
  speak() {
    (() => {
      console.log(this);
    })();
  }
};
obj3.speak();

여기서는 마치 내부처럼 보일 수도 있습니다. speak 우리는 화살표 함수를 실행합니다. 이렇게 하면 전역 설정으로 "초기화"됩니다.하지만 정반대의 일이 일어납니다. 화살표 함수는 다음을 포착합니다. this 그것을 둘러싼 기능의이 경우 그것은 방법입니다. speak 소환됨 obj3.speak()따라서, 그 값은 this 콘솔에 표시된 것은 바로 그 제품입니다. obj3.

내 말은, 화살표 함수는 자체적인 기능을 가지고 있지 않습니다. this오히려 주변 환경의 것을 재활용한다.이 기능은 중첩 콜백, 타이머, 프로미스 등 기존 함수로는 어려움을 겪었던 모든 곳에서 매우 유용합니다. .bind 또는 다음과 같은 트릭을 사용해서 const that = this;.

손실과 보존의 실제 사례 this

자바스크립트에서 흔히 발생하는 문제 중 하나는 메서드 내부에 함수를 정의할 때, 참조를 잃게 됩니다 this 그것이 물체를 가리켰다 그러면 결국 글로벌 버전이나 다른 버전을 얻게 됩니다. undefined.

일반적인 사용 사례를 살펴보겠습니다. setTimeout 기존 함수를 가진 객체의 메서드 내에서:

const persona = {
  nombre: 'Agustin',
  decirNombre: function() {
    setTimeout(function() {
      console.log(this.nombre);
    }, 3000);
  }
};
persona.decirNombre(); // Muestra undefined

여기에 이것은 전달된 함수 내부에 있습니다. setTimeout 그것은 더 이상 대상이 아닙니다. persona해당 콜백 함수는 전역 컨텍스트(브라우저에서)에서 실행됩니다. window), 그래서 this.nombre 전역 변수에 존재하지 않는 속성을 읽으려고 시도하여 결국 오류가 발생합니다. undefined.

화살표 함수가 존재하기 전에는 일반적인 해결책으로 해당 값을 저장하는 방식이 사용되었습니다. this 보조 변수에서 함수 안으로 "드래그"하려면:

const persona = {
  nombre: 'Agustin',
  decirNombre: function() {
    let that = this; // aquí this es persona
    setTimeout(function() {
      console.log(that.nombre);
    }, 3000);
  }
};

그 변수 덕분에 객체에 대한 올바른 참조가 유지됩니다. 하지만 이는 다소 보기 흉하고 반복적인 방법입니다. 화살표 함수를 사용하면 이 문제가 훨씬 간단해집니다.

const persona = {
  nombre: 'Agustin',
  decirNombre: function() {
    setTimeout(() => {
      console.log(this.nombre);
    }, 3000);
  }
};

여기서 화살표 함수는 자체적으로 함수를 생성하지 않습니다. this, 그래서 상속됩니다 this 방법의 decirNombre그것은 객체입니다 persona결과: 중간 변수 없이도 "Agustin"이 올바르게 표시됩니다. .bind.

호출, 적용 및 바인딩: 값 제어 this

메서드 호출을 통해 컨텍스트를 설정하는 "자연스러운" 방식 외에도 JavaScript는 다음과 같은 도구를 제공합니다. 값을 강제로 this 정상 기능에서: call, apply y bind.

행동 양식 call() y apply() 이들은 함수를 즉시 호출하므로 사용하려는 객체를 전달할 수 있습니다. this. 차이점은 call 인수를 하나씩 받아들이는 동안 apply 그것들은 배열 형태로 수신됩니다. bind()대신, 다음과 같은 새로운 함수를 반환합니다. this 귀하께서 표시하신 값에 "첨부"됩니다.나중에 편한 시간에 그녀에게 전화하시면 됩니다.

하지만 화살표 함수의 경우 이러한 방법은 값을 변경하는 데 유용하지 않습니다. this 그 값이 어휘적으로 연결되어 있기 때문입니다.. 당신이 사용할 수있는 call, apply o bind 인수를 전달할 수는 있지만 화살표 함수의 컨텍스트를 수정할 수는 없다는 점이 일반 함수와의 매우 중요한 차이점입니다.

화살표 함수의 기본 구문

행동 그 너머 this화살표 함수는 다음을 제공합니다. 보다 간결하고 표현력이 풍부한 구문 여러 상황에서 사용됩니다. 일반적인 형식은 다음과 같습니다.

(arg1, arg2, ..., argN) => expresion

이 형식은 화살표 오른쪽에 있는 표현식의 결과를 자동으로 반환합니다. 그 단어를 쓸 필요가 없습니다. return 단 하나의 간단한 표현식만 있을 때.

구문의 몇 가지 공통적인 특징:

  • 매개변수 없이:
    () => 42 또는 _ => 42 인자 이름에 신경 쓰지 않는다면.
  • 단일 매개변수로:
    괄호는 선택 사항이며, 다음과 같이 작성할 수 있습니다. x => x * 2 o (x) => x * 2.
  • 여러 매개변수를 사용하여:
    괄호는 필수입니다. (x, y) => x + y.

여러 개의 명령문이 필요할 때는 다음을 사용할 수 있습니다. 블록 본체 키 포함:

const sumar = (x, y) => {
  const resultado = x + y;
  return resultado;
};

이 경우에는 열쇠가 있으므로, 암묵적인 반환은 더 이상 존재하지 않습니다.만약 당신이 넣지 않는다면 return함수는 다음을 반환합니다. undefined이는 화살표 함수와 일반 함수 모두에 적용됩니다.

화살표 함수를 사용하면 리터럴 객체를 반환합니다.

작지만 매우 흔한 구문상의 세부 사항이 있습니다. 화살표 함수가 반환값을 가질 때입니다. 문자 그대로의 객체인터프리터가 이를 블록으로 오인하지 않도록 괄호로 묶어야 합니다.

예를 들면 다음과 같습니다

x => ({ y: x })

괄호가 없으면 자바스크립트는 중괄호를 객체가 아닌 함수 본문의 시작으로 해석합니다. 간단한 요령이지만, 잊어버리면 어처구니없는 실수가 많이 발생합니다.

화살표 함수: 익명 및 프로토타입 없음

화살표 함수는 구문적으로 익명그들은 고유한 이름이 없어서 상황이 다소 복잡해질 수 있습니다. 디버그 및 오류 메시지추적 로그에서는 함수 식별자를 직접 볼 수 없기 때문입니다. 식별 가능한 이름을 가진 상수에 함수 식별자를 할당한 경우에만 볼 수 있습니다.

또한 화살표 기능은 그들은 재산을 소유하지 않습니다. prototype 그리고 그들은 건설 회사로 사용될 수 없습니다.만약 당신이 그들을 소환하려고 한다면 new오류가 발생할 것입니다. 생성자나 클래스를 사용하여 객체를 생성하려면 여전히 일반 함수나 구문을 사용해야 합니다. class.

또 다른 결과는 다음과 같습니다. 내부적인 자기 참조가 필요한 패턴에는 적합하지 않습니다.예를 들어 재귀 호출이나 이벤트 핸들러처럼 구독을 해제해야 하는 경우 등이 있습니다. this 또는 함수 자체의 이름.

화살표 함수가 빛을 발하는 곳

화살표 함수의 가장 큰 강점은 바로 여기에 있습니다. 어휘 연결 this이는 다른 함수에 전달하는 콜백 함수가 특정 상태를 유지하도록 하려는 상황에 이상적입니다. this 주변 지역의.

예를 들어, 타이머를 시작하고 지속적으로 접근해야 하는 메서드를 가진 객체의 경우 객체 자체의 속성을 사용하여 this:

const contador = {
  id: 42,
  iniciar() {
    setTimeout(() => {
      console.log(this.id); // this es contador
    }, 1000);
  }
};

ES5에서는 다음과 같은 경우가 흔했습니다. .bind(this) 콜백 또는 저장 this 다른 변수에 저장합니다. 화살표 함수를 사용하면, 코드가 더 깔끔해지고 실제 의도에 더 가까워집니다..

또한 배열 메서드와 같은 실용적인 기능도 제공합니다. map, filter, reduce 그리고 회사, 왜냐하면 구문적 잡음을 줄입니다 함수의 논리가 간략할 경우:

const numeros = [1, 2, 3];
const dobles = numeros.map(n => n * 2);

이러한 간결한 형태를 적절히 사용하면 데이터의 흐름을 한눈에 더 쉽게 파악할 수 있습니다.

화살표 함수를 피해야 하는 경우

화살표 함수는 매우 유용하지만 일반 함수를 대체할 수는 없습니다. 일반 함수가 아닌 다른 함수를 사용해야 하는 몇 가지 분명한 경우가 있습니다. 사용하지 않는 것이 가장 좋습니다.:

  • 객체 메서드는 의존적입니다. this:
    메서드를 다음과 같이 정의하는 경우 saltos: () => { this.vidas--; } 물체 내부 gato, this 고양이 때문이 아니라 외부 환경 때문일 것이고, 부동산은 당신이 기대하는 대로 변화하지 않을 것입니다.
  • DOM 이벤트 콜백은 다음을 필요로 합니다. this 동적:
    핸들러에서 다음과 같이 boton.addEventListener('click', () => { this.classList.toggle('on'); });, this 버튼이 눌린 것 자체가 아니라, 더 상위 컨텍스트에서 오타가 발생할 가능성이 높습니다.
  • 빌더 또는 필요한 기능 prototype:
    함께 사용할 수 없기 때문에 new화살표 함수는 인스턴스를 생성하거나 프로토타입 기반 패턴에 적합하지 않습니다.

이 모든 경우에 있어서, 정상적인 기능은 여전히 ​​적절한 도구로 남아 있습니다. 왜냐하면 그것은 그것을 가능하게 해주기 때문입니다. this 이는 함수를 호출하는 방식에 따라 동적으로 연결됩니다.

일반 함수와 화살표 함수 중에서 필요에 따라 의식적으로 선택하는 데 익숙해지면 this 그리고 문맥상, 코드가 더 예측 가능하고 읽기 쉬워질 것입니다. 나중에 그것을 보관하는 사람들을 위해서.

궁극적으로, 그 가치를 이해하는 것이 중요합니다. this 자바스크립트에서 화살표 함수가 해당 값을 상속받는 방식 예상치 못한 결과로 어려움을 겪는 것을 멈추고, ES6의 구문적 편의 기능을 활용하며, 의도한 대로 작동하는 메서드, 콜백 및 이벤트 핸들러를 작성하는 핵심은 이러한 요소들이 생성되는 어휘적 범위를 이해하는 것입니다.