类 和 React 组件中的 this 关键字行为(箭头函数与常规函数)
this keyword behavior in classes and react component ( Arrow function vs regular function)
我正在尝试了解 this 关键字在与事件处理程序配对时在反应组件中的行为(箭头函数与常规函数)。
为此,我创建了两个示例,一个使用 HTML/vanilla JS,另一个使用 React。
HTML/VanillaJS
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button class="btn-arr">Log this Arr</button>
<button class="btn-reg">Log this Reg</button>
<script>
class App {
logThisArr = () => {
console.log('Arr : ', this);
};
logThisReg = function () {
console.log('Reg : ', this);
};
}
const app = new App();
const btnArr = document.querySelector('.btn-arr');
const btnReg = document.querySelector('.btn-reg');
btnArr.addEventListener('click', app.logThisArr); // Arr : App {logThisArr: ƒ, logThisReg: ƒ}
btnReg.addEventListener('click', app.logThisReg); // Reg : <button class="btn-reg">Log this Reg</button>
</script>
</body>
</html>
反应
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import registerServiceWorker from './registerServiceWorker';
class App extends Component {
logThisArr = () => {
console.log('arrow : ', this);
};
logThisReg = function() {
console.log('Reg : ', this);
};
render() {
return (
<div className="App">
<button onClick={this.logThisArr}>Log this Arr</button>
{/* Arr : App {props: {…}, context: {…}, refs: {…}, updater: {…}, logThisArr: ƒ, …}*/}
<button onClick={this.logThisReg}>Log this Reg</button>
{/*Reg : undefined */}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
为什么我在使用常规函数时得不到相同的输出?
在反应中,我得到 "undefined",在 vanillaJS 中,我得到按钮对象。
谢谢!
您不必处理 this
。但不要忘记绑定回调事件 ( React Doc about events ) 以始终拥有良好的 ref
只需将此添加到 App 组件
constructor(props) {
super(props);
this.logThisArr = this.logThisArr.bind(this);
this.logThisReg = this.logThisReg.bind(this);
}
好的,那么,谢谢你们。
经过大量阅读,我觉得我理解得更好一些。
它比原来的 post 更深入。
我们首先需要了解"execution context"和"lexical scope"的区别。
http://ryanmorr.com/understanding-scope-and-context-in-javascript/
然后我们可以开始查看 "this" 在常规函数和箭头函数中的行为。
正则函数内部:
- "this" 值根据 "execution context" 而变化,换句话说,"this" 是对调用它的人或对象的引用(通常是一个对象,即按钮对象或 class 实例化对象)。
- 如果 "nothing" 调用它(尤其是回调的情况),那么 "this" 将失去对调用它的初始对象的引用并设置为默认值(该默认值取决于我们是在节点中,还是在浏览器中,还是在严格模式下,还是在使用库(不确定库,但我认为?))
- 可以使用 "call()"、"apply()" 和 "bind()".
显式指定 "this" 值
内部箭头函数:
- 箭头函数没有自己的 "execution context"
- 箭头函数在声明中静态绑定上下文,换句话说,"this" 的值是永久的 "captured" 并且它几乎总是引用 "this" 的值函数的 "parent/enclosing lexical scope"(=父上下文)。
- "this" 值永远无法重新绑定。但是箭头函数中的其他参数可以用 "bind()" 关键字重新绑定。
- 在对象文字中使用箭头函数定义方法的特殊情况下,"this" 指的是 window 对象:https://dmitripavlutin.com/when-not-to-use-arrow-functions-in-javascript/
这就是为什么在 react 中使用箭头函数或使用“.bind()”是必要的,因为我们不能依赖常规函数(其中 "this" 不断变化)来访问属性我们实例化的 App class.
对象
在我们的具体情况下,至于为什么我在反应代码中使用常规功能时得到 "undefined",TBT 我不太确定(可能是因为反应内部恶作剧)但我可以猜到这是因为两件事:
- "this" 丢失了它的 "execution context"(换句话说,它丢失了对调用它的对象的引用)所以它成为默认值(或者 "undefined",当在 "strict mode", 或 "window object" 当不在严格模式和浏览器中时)
- 在 ES6 classes 中,默认的隐式设置设置为 "strict mode",因此我们得到 "undefined".
无论如何,这并不详尽,我还没有完全理解,但我现在更好地理解了为什么我们需要 bind/use React 中的箭头功能以及它们的工作原理。
这些真的帮助我弄清了事情的真相:
- https://blog.bitsrc.io/what-is-this-in-javascript-3b03480514a7
- https://www.freecodecamp.org/news/the-magic-of-the-this-keyword-in-javascript-ce3ce571013e/
- https://medium.com/free-code-camp/learn-es6-the-dope-way-part-ii-arrow-functions-and-the-this-keyword-381ac7a32881#.59q9th108
还有@brian Thomoson 提到的link:
How to access the correct `this` inside a callback?
谢谢大家
此致,
我正在尝试了解 this 关键字在与事件处理程序配对时在反应组件中的行为(箭头函数与常规函数)。
为此,我创建了两个示例,一个使用 HTML/vanilla JS,另一个使用 React。
HTML/VanillaJS
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button class="btn-arr">Log this Arr</button>
<button class="btn-reg">Log this Reg</button>
<script>
class App {
logThisArr = () => {
console.log('Arr : ', this);
};
logThisReg = function () {
console.log('Reg : ', this);
};
}
const app = new App();
const btnArr = document.querySelector('.btn-arr');
const btnReg = document.querySelector('.btn-reg');
btnArr.addEventListener('click', app.logThisArr); // Arr : App {logThisArr: ƒ, logThisReg: ƒ}
btnReg.addEventListener('click', app.logThisReg); // Reg : <button class="btn-reg">Log this Reg</button>
</script>
</body>
</html>
反应
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import registerServiceWorker from './registerServiceWorker';
class App extends Component {
logThisArr = () => {
console.log('arrow : ', this);
};
logThisReg = function() {
console.log('Reg : ', this);
};
render() {
return (
<div className="App">
<button onClick={this.logThisArr}>Log this Arr</button>
{/* Arr : App {props: {…}, context: {…}, refs: {…}, updater: {…}, logThisArr: ƒ, …}*/}
<button onClick={this.logThisReg}>Log this Reg</button>
{/*Reg : undefined */}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
为什么我在使用常规函数时得不到相同的输出? 在反应中,我得到 "undefined",在 vanillaJS 中,我得到按钮对象。
谢谢!
您不必处理 this
。但不要忘记绑定回调事件 ( React Doc about events ) 以始终拥有良好的 ref
只需将此添加到 App 组件
constructor(props) {
super(props);
this.logThisArr = this.logThisArr.bind(this);
this.logThisReg = this.logThisReg.bind(this);
}
好的,那么,谢谢你们。
经过大量阅读,我觉得我理解得更好一些。
它比原来的 post 更深入。 我们首先需要了解"execution context"和"lexical scope"的区别。 http://ryanmorr.com/understanding-scope-and-context-in-javascript/
然后我们可以开始查看 "this" 在常规函数和箭头函数中的行为。
正则函数内部:
- "this" 值根据 "execution context" 而变化,换句话说,"this" 是对调用它的人或对象的引用(通常是一个对象,即按钮对象或 class 实例化对象)。
- 如果 "nothing" 调用它(尤其是回调的情况),那么 "this" 将失去对调用它的初始对象的引用并设置为默认值(该默认值取决于我们是在节点中,还是在浏览器中,还是在严格模式下,还是在使用库(不确定库,但我认为?))
- 可以使用 "call()"、"apply()" 和 "bind()". 显式指定 "this" 值
内部箭头函数:
- 箭头函数没有自己的 "execution context"
- 箭头函数在声明中静态绑定上下文,换句话说,"this" 的值是永久的 "captured" 并且它几乎总是引用 "this" 的值函数的 "parent/enclosing lexical scope"(=父上下文)。
- "this" 值永远无法重新绑定。但是箭头函数中的其他参数可以用 "bind()" 关键字重新绑定。
- 在对象文字中使用箭头函数定义方法的特殊情况下,"this" 指的是 window 对象:https://dmitripavlutin.com/when-not-to-use-arrow-functions-in-javascript/
这就是为什么在 react 中使用箭头函数或使用“.bind()”是必要的,因为我们不能依赖常规函数(其中 "this" 不断变化)来访问属性我们实例化的 App class.
对象在我们的具体情况下,至于为什么我在反应代码中使用常规功能时得到 "undefined",TBT 我不太确定(可能是因为反应内部恶作剧)但我可以猜到这是因为两件事:
- "this" 丢失了它的 "execution context"(换句话说,它丢失了对调用它的对象的引用)所以它成为默认值(或者 "undefined",当在 "strict mode", 或 "window object" 当不在严格模式和浏览器中时)
- 在 ES6 classes 中,默认的隐式设置设置为 "strict mode",因此我们得到 "undefined".
无论如何,这并不详尽,我还没有完全理解,但我现在更好地理解了为什么我们需要 bind/use React 中的箭头功能以及它们的工作原理。
这些真的帮助我弄清了事情的真相:
- https://blog.bitsrc.io/what-is-this-in-javascript-3b03480514a7
- https://www.freecodecamp.org/news/the-magic-of-the-this-keyword-in-javascript-ce3ce571013e/
- https://medium.com/free-code-camp/learn-es6-the-dope-way-part-ii-arrow-functions-and-the-this-keyword-381ac7a32881#.59q9th108
还有@brian Thomoson 提到的link: How to access the correct `this` inside a callback?
谢谢大家
此致,