>  기사  >  웹 프론트엔드  >  JS에서 'this' 포인터를 처리하는 여러 가지 방법

JS에서 'this' 포인터를 처리하는 여러 가지 방법

尚
앞으로
2020-06-18 17:18:031979검색

JS에서 'this' 포인터를 처리하는 여러 가지 방법

저는 JS에서 this 포인터라고도 알려진 함수 실행 컨텍스트의 포인터를 변경하는 것을 좋아합니다. this 指向。

例如,咱们可以在类数组对象上使用数组方法:

const reduce = Array.prototype.reduce;

function sumArgs() {
  return reduce.call(arguments, (sum, value) => {
    return sum += value;
  });
}

sumArgs(1, 2, 3); // => 6

另一方面,this 很难把握。

咱们经常会发现自己用的 this 指向不正确。下面的教你如何简单地将 this 绑定到所需的值。

在开始之前,我需要一个辅助函数execute(func),它仅执行作为参数提供的函数。

function execute(func) {
  return func();
}

execute(function() { return 10 }); // => 10

现在,继续理解围绕this错误的本质:方法分离。

1.方法分离问题

假设有一个类Person包含字段firstNamelastName。此外,它还有一个方法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('前端', '小智')。函数内部的 this 表示新创建的实例。

getfullname()返回此人的全名:'前端 小智'。正如预期的那样,getFullName()方法内的 this 等于agent

如果辅助函数执行agent.getFullName方法会发生什么:

execute(agent.getFullName); // => 'undefined undefined'

执行结果不正确:'undefined undefined',这是 this 指向不正确导致的问题。

现在在getFullName() 方法中,this的值是全局对象(浏览器环境中的 window )。this 等于 window${window.firstName} ${window.lastName} 执行结果是 'undefined undefined'

发生这种情况是因为在调用execute(agent.getFullName)时该方法与对象分离。基本上发生的只是常规函数调用(不是方法调用):

execute(agent.getFullName); // => 'undefined undefined'

// 等价于:

const getFullNameSeparated = agent.getFullName;
execute(getFullNameSeparated); // => 'undefined undefined'

这个就是所谓的方法从它的对象中分离出来,当方法被分离,然后执行时,this 与原始对象没有连接。

为了确保方法内部的this指向正确的对象,必须这样做

  1. 以属性访问器的形式执行方法:agent.getFullName()

    예를 들어 배열 같은 객체에 배열 메서드를 사용할 수 있습니다.
  2. // `methodHandler()`中的`this`是全局对象
    setTimeout(object.handlerMethod, 1000);
  3. 반면에 이것은 이해하기 어렵습니다. this绑定到包含的对象(使用箭头函数、.bind()方法等)

方法分离问题,以及由此导致this指向不正确,一般会在下面的几种情况中出现:

回调

// React: `methodHandler()`中的`this`是全局对象
<button onClick={object.handlerMethod}>
  Click me
</button>

在设置事件处理程序时

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(&#39;前端&#39;, &#39;小智&#39;);

agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;

接着介绍一些有用的方法,即如果方法与对象分离,如何使this指向所需的对象。

2. 关闭上下文

保持this指向类实例的最简单方法是使用一个额外的变量self:

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;

  this.getFullName = () => `${this.firstName} ${this.lastName}`;
}

const agent = new Person(&#39;前端&#39;, &#39;小智&#39;);

agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;

getFullName()静态地关闭self变量,有效地对this进行手动绑定。

现在,当调用execute(agent.getFullName)时,一切工作正常,因为getFullName()方法内 this 总是指向正确的值。

3.使用箭头函数

有没有办法在没有附加变量的情况下静态绑定this?是的,这正是箭头函数的作用。

使用箭头函数重构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); // => &#39;undefined undefined&#39;

箭头函数以词法方式绑定this。简单来说,它使用来自其定义的外部函数this的值。

建议在需要使用外部函数上下文的所有情况下都使用箭头函数。

4. 绑定上下文

现在让咱们更进一步,使用ES6中的类重构Person

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(&#39;前端&#39;, &#39;小智&#39;);

agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;

不幸的是,即使使用新的类语法,execute(agent.getFullName)仍然返回“undefined undefined”

在类的情况下,使用附加的变量self或箭头函数来修复this的指向是行不通的。

但是有一个涉及bind()方法的技巧,它将方法的上下文绑定到构造函数中:

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  getFullName = () => {
    return `${this.firstName} ${this.lastName}`;
  }
}

const agent = new Person(&#39;前端&#39;, &#39;小智&#39;);

agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;

构造函数中的this.getFullName = this.getFullName.bind(this)将方法getFullName()绑定到类实例。

execute(agent.getFullName) 按预期工作,返回'前端 小智'

5. 胖箭头方法

bind

우리가 사용하는 this가 잘못된 것을 가리키는 경우가 종종 있습니다. 다음은 this를 원하는 값에 간단히 바인딩하는 방법을 알려줍니다. 🎜🎜시작하기 전에 인수로 제공된 함수를 실행하는 도우미 함수 execute(func)가 필요합니다. 🎜rrreee🎜이제 this를 둘러싼 오류의 본질, 즉 메서드 분리를 이해해 보세요. 🎜

1. 메소드 분리 문제🎜🎜 firstNamePerson 클래스가 있다고 가정합니다. /code> 및 . 또한 사람의 전체 이름을 반환하는 getFullName() 메서드도 있습니다. 아래와 같이 🎜rrreee🎜Person 함수가 생성자로 호출되는 것을 볼 수 있습니다: new Person('front-end', 'Xiao Zhi'). 함수 내부의 this는 새로 생성된 인스턴스를 나타냅니다. 🎜🎜getfullname()사용자의 전체 이름을 반환합니다: '프런트 엔드 Xiaozhi'. 예상대로 getFullName() 메서드 내의 thisagent와 같습니다. 🎜🎜도우미 함수가 agent.getFullName 메서드를 실행하면 어떻게 될까요? 🎜rrreee🎜실행 결과가 올바르지 않습니다: 'undefine undefine', 이는 이것입니다. 잘못된 포인팅으로 인해 발생한 문제입니다. 🎜🎜이제 getFullName() 메서드에서 this의 값은 전역 개체(브라우저 환경의 window)입니다. thiswindow와 동일하며 ${window.firstName} ${window.lastName}의 실행 결과는 '정의되지 않음 정의되지 않음'. 🎜🎜이는 execute(agent.getFullName)이 호출될 때 메서드가 개체에서 분리되기 때문에 발생합니다. 기본적으로 일어나는 일은 (메서드 호출이 아닌) 일반적인 함수 호출입니다: 🎜rrreee🎜 이것은 객체에서 메소드를 분리하는 것입니다. 메소드가 분리된 후 실행될 때 이것은 원본 개체와 동일 연결이 없습니다. 🎜🎜메서드 내의 this가 올바른 개체를 가리키는지 확인하려면 이 작업을 수행해야 합니다.🎜

    🎜🎜속성 접근자: agent 형식으로 메서드를 실행하세요. getFullName() 🎜🎜🎜 또는 this를 포함된 개체에 정적으로 바인딩합니다(화살표 함수, .bind() 메서드 등 사용).
    🎜
🎜 메서드 분리 문제, this를 잘못 가리키는 경우는 일반적으로 다음 상황에서 발생합니다. 🎜🎜콜백🎜rrreee🎜이벤트 핸들러를 설정할 때 🎜rrreee🎜 그런 다음 몇 가지 유용한 메소드를 소개합니다. 즉, 메소드가 객체와 분리된 경우 this가 필요한 객체를 가리키도록 만드는 방법을 소개합니다. 🎜

2. 컨텍스트 닫기🎜🎜 this가 클래스 인스턴스를 가리키는 가장 쉬운 방법은 추가 항목을 사용하는 것입니다. 변수self: 🎜rrreee🎜getFullName()self 변수를 정적으로 닫아 this를 효과적으로 수동으로 바인딩합니다. 🎜🎜이제 execute(agent.getFullName)을 호출하면 getFullName() 메서드 내부의 this가 항상 올바른 항목을 가리키기 때문에 모든 것이 잘 작동합니다. 값. 🎜

3. 화살표 함수 사용🎜🎜추가 변수 없이 this를 정적으로 바인딩할 수 있는 방법이 있나요? 예, 이것이 바로 화살표 기능이 하는 일입니다. 🎜🎜화살표 함수를 사용하여 Person을 재구성합니다. 🎜rrreee🎜화살표 함수는 this를 어휘적으로 바인딩합니다. 간단히 말해서, 정의된 외부 함수 this의 값을 사용합니다. 🎜🎜외부 함수 컨텍스트를 사용해야 하는 모든 경우에는 화살표 함수를 사용하는 것이 좋습니다. 🎜

4. 컨텍스트 바인딩🎜🎜이제 한 단계 더 나아가 ES6의 클래스를 사용하여 Person을 리팩터링해 보겠습니다. 🎜rrreee🎜안타깝게도 새 클래스 구문을 사용해도 execute(agent.getFullName)는 여전히 "undefunction undefine"을 반환합니다. 🎜🎜클래스의 경우 추가 변수 self나 화살표 함수를 사용하여 this의 포인팅을 수정하는 것은 작동하지 않습니다. 🎜🎜그러나 메서드의 컨텍스트를 생성자에 바인딩하는 bind() 메서드와 관련된 트릭이 있습니다. 🎜rrreee🎜this.getFullName = 생성자 바인딩에서 this.getFullName. (this)getFullName() 메서드를 클래스 인스턴스에 바인딩합니다. 🎜🎜execute(agent.getFullName)가 예상대로 작동하여 'frontend Xiaozhi'를 반환합니다. 🎜

5. 굵은 화살표 방법🎜🎜bind 이 방법은 너무 장황하므로 굵은 화살표를 사용할 수 있습니다. 방법: 🎜

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  getFullName = () => {
    return `${this.firstName} ${this.lastName}`;
  }
}

const agent = new Person(&#39;前端&#39;, &#39;小智&#39;);

agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;

胖箭头方法getFullName =() =>{…}绑定到类实例,即使将方法与其对象分离。

这种方法是在类中绑定this的最有效和最简洁的方法。

6. 总结

与对象分离的方法会产生 this 指向不正确问题。静态地绑定this,可以手动使用一个附加变量self来保存正确的上下文对象。然而,更好的替代方法是使用箭头函数,其本质上是为了在词法上绑定this

在类中,可以使用bind()方法手动绑定构造函数中的类方法。当然如果你不用使用 bind 这种冗长方式,也可以使用简洁方便的胖箭头表示方法。

更多JavaScript知识请关注PHP中文网JavaScript视频教程栏目

위 내용은 JS에서 'this' 포인터를 처리하는 여러 가지 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 csdn.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제