关于此主题的问题已经有好几个了,我已经查看了所发现的所有内容-我的问题是为了为我自己消除一些正在出现的(明显的)矛盾。我怀疑有比我目前唯一的解决方案更好的解决方案。我是Java语言的新手。
我已经阅读了this
上的范围规则,例如https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this。从阅读中我的理解是,尽管很大程度上取决于调用上下文,但是如果函数是对象的方法,则函数this
中的对象将是对象本身。我以为这个规则胜过其他规则,但也许我误会了。
我还阅读了https://medium.com/byte-sized-react/what-is-this-in-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)
解决方案更好的解决方案?每个方法向构造函数添加一行额外的代码,以显式绑定我的所有方法,似乎很麻烦。
答案 0 :(得分:3)
箭头函数将您的函数直接绑定到类。但是,如果您使用
const clickFunction = () => { ... }
这将创建一个内部函数,并且不会将其绑定到类。
您可以使用
clickFunction = () => { ... }
与
类似 this.clickFunction = this.clickFunction.bind(this);
答案 1 :(得分:1)
您是对的,当从对象调用函数时,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
的值。这将是正在构造的对象。
箭头函数执行相同的操作,但是没有显式绑定。实际上,这实际上是箭头功能和常规功能之间的功能差异,许多人通常会忽略它们,因为它们通常是出于样式或简洁的目的而选择的。可以说,箭头函数的行为像大多数程序员所期望的 ,而普通函数的行为是Java脚本特有的(因此相当混乱)。
答案 2 :(得分:0)
第二个箭头方法,它将在此方法定义的地方(而不是从调用它的地方)引用此参考。因此它将采用该类的参考。
答案 3 :(得分:0)
您有有效的积分
为什么教程有效?如果看到renderSquare实现,您会注意到它在实现中未使用this
,因此它不必与此绑定。您的实现可能无法正常运行,因为您可能在方法实现内部使用了this
。
renderSquare(i) {
return <Square value={i} />;
}
当您获得诸如this.clickFunction
之类的引用时,您只会得到未绑定到任何对象的特定函数的引用,这就是为什么如果尝试使用this
来引用变量,则调用该函数将失败的原因
请参阅此小提琴https://jsfiddle.net/yh3jw5nk/1/以获取更多说明
答案 4 :(得分:0)
这是在运行时确定的,取决于代码,它可能有所不同。
这是
示例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:使用方法调用检查 this
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
。