已经有几个关于这个主题的问题,我已经查看了我发现的所有问题 - 我的问题是为了为自己清除一些(显然(的矛盾,我看到。我怀疑有一个比我现在唯一工作的解决方案更好的解决方案。我是JavaScript的新手。
我已经阅读了this
上的范围规则,例如https://developer.mozilla.org/en-us/docs/web/javascript/reference/reference/operators/this。我从阅读中的理解是,尽管很大程度上取决于呼叫上下文,但如果函数是对象的方法,则函数 this
中的对象本身将是对象本身。我认为这个规则胜过其他规则,但也许我已经误解了。
我还在https://medium.com/byte-sied-react/what-is-this-react-25c62c31480上阅读了一篇文章通过this
,我有
class App extends Component {
constructor(props) {
super(props);
}
clickFunction() {
console.log(this.props.value);
}
render() {
return(
<div onClick={this.clickFunction}>Click Me!</div>
);
}
}
然后,我需要通过在构造器中添加一条线(例如
(将对象明确地绑定到clickFunction()
this.clickFunction = this.clickFunction.bind(this);
或使用箭头符号来定义 clickFunction()
,例如
const clickFunction = () => { ... }
这些解决方案中的第一个对我有用 - 我没有第二次工作。对我来说,我需要使用任何一种解决方案似乎很奇怪,因为(a(似乎与文档中的主张相矛盾,即对象方法将对象视为this
,并且(b(我看不到人们在我看的其他教程示例中做这种事情。
例如,在https://reactjs.org/tutorial/tutorial.html上有一个React教程,该方法定义了诸如renderSquare(i)
之类的对象方法,并且在任何时候都不会明确地将这些方法绑定到对象上。
如果我尝试做一些与该教程完全类似的事情,并且不要明确地将行添加到构造函数以将每个方法绑定到对象,即诸如this.clickFunction = this.clickFunction.bind(this)
之类的行,那么我无法获得我的代码上班。
谁能向我解释我对教程和文档的误解 - 为什么教程即使对对象没有明确的约束力,教程也可以工作?我可以在它和我自己的代码之间发现的唯一区别是我有use strict
。是否有比我当前正在使用的this.clickFunction.bind(this)
解决方案更好的修复方法?每个方法向构造函数添加一条额外的代码,以明确绑定我的所有方法,似乎很笨拙。
箭头函数将您的功能绑定到类直接地。但是,如果您使用
const clickFunction = () => { ... }
这将创建一个内部函数,并且不将其绑定到类。
您可以使用
clickFunction = () => { ... }
将类似于
this.clickFunction = this.clickFunction.bind(this);
是正确的,当从对象调用函数时, this
关键字最终成为该对象。因此运行类似:
const app = new App();
app.clickFunction();
会产生您期望的结果,因为它直接从App
类调用。
但是,当您将该功能用作JSX中的事件处理程序时,您将作为回调的引用来传递该功能。默认情况下,函数的this
关键字在调用后才确定,因此它将根据调用的词汇上下文分配。您可以想象,当您设置处理程序时,类似以下的事情正在引擎盖下发生:
const callback = app.clickFunction;
// click event happens
callback(event);
在这里您可以看到callback()
的调用只是一个裸露的函数调用。没有app.
前缀为this
提供词汇上下文。
您已经列出的围绕此行为的两种方式将this
关键字明确设置为他们最初使用的对象。调用this.clickFunction = this.clickFunction.bind(this)
是最明确的,因为它采用正常功能,并在对象构造过程中手动将this
绑定到this
的值。这将是要构造的对象。
箭头功能执行相同的事情,但没有明确的绑定。这实际上是箭头功能和常规功能之间的功能差异,因为它们通常是出于风格或简洁的目的而掩饰的,因为它们通常会掩饰。可以说,箭头函数的行为正如大多数程序员所期望的那样,而正常函数的行为是JavaScript非常独特的(因此非常令人困惑(。
第二箭头方法,它将采用此参考,其中定义该方法的定义不是从称呼的位置。因此,这将接受此类参考。
参考。这在箭头功能
您有有效的点
为什么教程工作?如果您看到RenderSquare实现,您会注意到它在其实现中不使用this
,因此它不必使用它来束缚自己。您的实现可能无法使用,因为您可能在方法实现中使用了this
。
renderSquare(i) {
return <Square value={i} />;
}
当您获得诸如this.clickFunction
之类的引用时,您只会获得该特定函数的引用,该功能未绑定到任何对象,这就是为什么尝试使用this
请参阅此小提琴https://jsfiddle.net/yh3jw5nk/1/有关更多解释的信息,它可能是不同的。
这是
- 在运行时确定函数时
- 取决于如何调用函数,而不是函数在哪里定义
- 对对象的引用。
- 将永远是一个对象
- 全局(这(在严格模式下不可用
示例1: this = window
var name = 'Global';
var callName1 = function() {
var name = 'Peter';
console.log('--- From callName1 ----');
console.log(this.name);
//console.log(this);
callName2();
}
var callName2 = function() {
var name = 'Jane';
console.log('--- From callName2 ----');
console.log(this.name);
//console.log(this);
}
callName1();
var execute = function(fn) {
var name = 'Mary';
console.log('--- From execute ----');
console.log(this.name);
//console.log(this);
}
execute(callName2);
示例2:在严格模式下不可用
'use strict';
var name = 'Global';
var callName1 = function() {
var name = 'Peter';
console.log('--- From callName1 ----');
console.log(this.name);
console.log(this);
}
callName1();
示例3:使用方法调用
检查
var name = 'global';
var obj = {
name: 'James Obj1',
func: function() {
console.log('--- From func ----');
console.log(this.name);
console.log(this); // this reference obj1
}
}
obj.func()
var obj2 = {
name: 'Jame Obj2',
func: obj.func // this reference obj2, but the function is defined in obj1
}
obj2.func()
var obj3 = {
name: 'Kane Obj3',
obj4: {
name: 'Mary Obj4',
func: function () {
console.log('--- From obj4 ----');
console.log(this.name);
console.log(this); // this reference obj4
}
}
}
obj3.obj4.func()
使用 () => {}
函数 this - 是词法绑定的。这意味着它使用包含箭头函数的代码中使用this
。