저는 JS에서 함수 실행 컨텍스트의 포인터(이 포인터라고도 함)를 변경하는 것을 좋아합니다.
예를 들어 배열과 유사한 객체에 배열 메서드를 사용할 수 있습니다.
const reduce = Array.prototype.reduce; function sumArgs() { return reduce.call(arguments, (sum, value) => { return sum += value; }); } sumArgs(1, 2, 3); // => 6
한편, 이는 이해하기 어렵습니다.
우리는 이것을 잘못 가리키는 데 사용하는 경우가 종종 있습니다. 다음에서는 이를 원하는 값에 간단히 바인딩하는 방법을 설명합니다.
【관련 강좌 추천: JavaScript 동영상 튜토리얼】
시작하기 전에 매개변수로 제공되는 함수만 실행하는 도우미 함수 실행(func)이 필요합니다.
function execute(func) { return func(); } execute(function() { return 10 }); // => 10
이제 이 문제를 둘러싼 오류의 본질인 메서드 분리를 이해하는 단계로 넘어갑니다.
1. 메소드 분리 문제
firstName 및 lastName 필드를 포함하는 Person 클래스가 있다고 가정합니다. 또한 사람의 전체 이름을 반환하는 getFullName() 메서드도 있습니다. 아래와 같이
function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; this.getFullName = function() { this === agent; // => true return `${this.firstName} ${this.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智'
Person 함수가 생성자로 호출되는 것을 볼 수 있습니다: new Person('front-end', 'Xiao Zhi'). 함수 내부의 이는 새로 생성된 인스턴스를 나타냅니다.
getfullname()은 사람의 전체 이름인 '프런트 엔드 Xiaozhi'를 반환합니다. 예상한 대로 getFullName() 메소드 내부의 이는 에이전트와 동일합니다.
보조 함수가 Agent.getFullName 메소드를 실행하면 어떻게 될까요?
execute(agent.getFullName); // => 'undefined undefined'
실행 결과가 잘못되었습니다: 'undefunction', 이는 잘못된 포인팅으로 인해 발생하는 문제입니다.
이제 getFullName() 메소드에서 this의 값은 전역 객체(브라우저 환경의 창)입니다. 이는 window와 동일하며, ${window.firstName} ${window.lastName}의 실행 결과는 'undefine undefine'입니다.
이러한 현상은 Execution(agent.getFullName)이 호출될 때 메소드가 객체에서 분리되기 때문에 발생합니다. 기본적으로 일어나는 일은 단지 일반적인 함수 호출입니다(메서드 호출이 아님).
execute(agent.getFullName); // => 'undefined undefined' // 等价于: const getFullNameSeparated = agent.getFullName; execute(getFullNameSeparated); // => 'undefined undefined'
이것을 객체에서 분리되는 메소드라고 합니다. 메소드가 분리된 후 실행되면 원본 객체와 연결이 없습니다.
1. 메소드 내에서 이것이 올바른 객체를 가리키는지 확인하려면 이 작업을 수행해야 합니다.
2. 속성 접근자(agent.getFullName()) 형식으로 메소드를 실행하거나 이를 포함된 객체에 정적으로 바인딩합니다. 객체(화살표 함수, .bind() 메소드 등 사용)
메서드 분리 문제 및 그에 따른 잘못된 지정은 일반적으로 다음 상황에서 발생합니다.
Callback
// `methodHandler()`中的`this`是全局对象 setTimeout(object.handlerMethod, 1000);
이벤트 핸들러를 설정할 때
// React: `methodHandler()`中的`this`是全局对象 <button onClick={object.handlerMethod}> Click me </button>
그런 다음 몇 가지 유용한 메소드를 소개합니다. 즉, 메소드가 객체와 분리된 경우 이 지점을 필수 객체로 만드는 방법을 소개합니다.
2. 컨텍스트 닫기
이 클래스 인스턴스를 계속 가리키는 가장 간단한 방법은 추가 변수 self:
function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; const self = this; this.getFullName = function() { self === agent; // => true return `${self.firstName} ${self.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
getFullName()을 사용하여 self 변수를 정적으로 닫고 이를 효과적으로 수동으로 바인딩하는 것입니다.
이제 실행(agent.getFullName)을 호출하면 getFullName() 메서드 내부가 항상 올바른 값을 가리키기 때문에 모든 것이 잘 작동합니다.
3. 화살표 함수 사용하기
추가 변수 없이 이것을 정적으로 바인딩하는 방법이 있나요? 예, 이것이 바로 화살표 기능이 하는 일입니다.
화살표 함수를 사용하여 Person:
function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; this.getFullName = () => `${this.firstName} ${this.lastName}`; } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
화살표 함수를 사용하여 이를 어휘적으로 바인딩합니다. 간단히 말해서, 정의된 외부 함수 this의 값을 사용합니다.
외부 함수 컨텍스트를 사용해야 하는 모든 경우에는 화살표 함수를 사용하는 것이 좋습니다.
4. 컨텍스트 바인딩
이제 한 단계 더 나아가 ES6의 클래스를 사용하여 Person을 리팩터링해 보겠습니다.
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } getFullName() { return `${this.firstName} ${this.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => 'undefined undefined'
불행하게도 새로운 클래스 구문을 사용하더라도 Execution(agent.getFullName)은 여전히 "undefine undefine"을 반환합니다.
클래스의 경우 추가 변수 self를 사용하거나 화살표 함수를 사용하여 이를 가리키는 것이 작동하지 않습니다.
하지만 메서드의 컨텍스트를 생성자에 바인딩하는 바인딩() 메서드와 관련된 트릭이 있습니다.
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; this.getFullName = this.getFullName.bind(this); } getFullName() { return `${this.firstName} ${this.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
this.getFullName = this.getFullName.bind(this) 생성자에서 할당된 getFullName() 메서드를 바인딩합니다. 클래스 인스턴스에.
execute(agent.getFullName)는 예상대로 작동하여 '프런트엔드 Xiaozhi'를 반환합니다.
5. 굵은 화살표 메소드
바인드 메소드는 너무 장황하므로 굵은 화살표 메소드를 사용할 수 있습니다.
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } getFullName = () => { return `${this.firstName} ${this.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
팻 화살표 메소드 getFullName =() =>{...}는 클래스에 바인딩됩니다. 인스턴스, 메소드가 해당 객체와 분리된 경우에도 마찬가지입니다.
이 방법은 이것을 클래스에 바인딩하는 가장 효율적이고 간결한 방법입니다.
6. 요약
메소드를 객체와 분리하면 이 포인팅이 잘못된 문제가 발생합니다. 이를 정적으로 바인딩하려면 추가 변수 self를 수동으로 사용하여 올바른 컨텍스트 개체를 보유할 수 있습니다. 그러나 더 나은 대안은 기본적으로 이를 어휘적으로 바인딩하는 역할을 하는 화살표 함수를 사용하는 것입니다.
클래스에서는 생성자의 클래스 메서드를 수동으로 바인딩하기 위해 바인딩() 메서드를 사용할 수 있습니다. 물론, 긴 바인딩 방법을 사용할 필요가 없다면 간결하고 편리한 굵은 화살표 표현 방법을 사용할 수도 있습니다.
원본 텍스트: https://github.com/valentinogagliardi/Little-JavaScript-Book/blob/v1.0.0/manuscript/chapter5.md
이 기사는 js tutorial 칼럼에서 가져온 것입니다. 학습을 환영합니다!
위 내용은 JS의 this 포인터를 올바르게 처리하는 5가지 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!