理解 JavaScript 中的“this”
函数中的'this'关键字由函数的执行范围决定。例如,使用obj.someFunction() 调用时,someFunction 中的this 将是obj。
一个更具体的例子:
function handleClick() {
console.log(this.state.value);
}
var state = { value: 1 }; // declare a var in window
console.log("handleClick()");
handleClick(); // Logged 1. The 'this' in the method will be window, because the method is called in window
var obj = {
state: { value: 2 },
handleClick: function() {
console.log(this.state.value);
},
};
console.log("obj.handleClick();");
obj.handleClick(); // Logged 2. The 'this' is referred to obj because the method is called in obj.
// let's reassign the function to a temp var in window
var temp = obj.handleClick;
console.log("temp()");
temp(); // Logged 1. The 'this' in the function is referred to window because the method is called in window.
console.log("window.temp()");
window.temp(); // this is equal to the one above.
console.log("temp.bind(obj)");
temp.bind(obj)(); // Logged 2. Bind the method and call the method, so the 'this' in the function is referred to obj.
console.log("temp.bind(this)");
temp.bind(this)(); // Logged 1. Since this in the executing scope is window. This effectively is the same calling in this.
console.log("temp.bind(window)");
temp.bind(window)(); // Logged 1. This is equal to the one above.
在这里试试:https://codepen.io/anon/pen/OvOpEa?editors=0012
关于此的博文:https://hackernoon.com/understanding-javascript-the-this-keyword-4de325d77f68
回到你的问题
如果您查看您在类中定义的render、componentWillMount 和handleSomething,就会明白为什么需要将处理程序绑定到this。
渲染
// Rerender
ReactCurrentOwner.current = workInProgress;
var nextChildren = void 0;
{
ReactDebugCurrentFiber.setCurrentPhase('render');
nextChildren = instance.render();
if (debugRenderPhaseSideEffects) {
instance.render();
}
ReactDebugCurrentFiber.setCurrentPhase(null);
}
这就是 react 调用 redner() 的方式,其中实例是具有状态、道具等的对象实例。您可以通过在渲染方法中放置断点并返回调用堆栈来非常轻松地尝试它。
handleSomething
例如,如果你这样定义你的类,用handleSomething作为按钮的onClick回调方法。
class Button extends Component {
handleSomething() {
// 'this' will be undefined.
}
render() {
return (<button onClick={this.handleSomething}>Test</button>);
}
}
如果你点击按钮,这就是 react 调用 onClick 处理方法的方式。
function callCallback() {
fakeNode.removeEventListener(evtType, callCallback, false);
// This is where react calls your method.
func.apply(context, funcArgs);
didError = false;
}
在我的调试经验中,func 是 handleSomething,context 通常是 undefined,funcArgs 是函数中传递的参数。
apply 类似于bind。第一个参数用于指定函数的this,第二个参数是传入函数的参数数组。
有关apply的更多信息,请参见MDN:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
在这种情况下,方法handleSomething 被调用,undefined 为this;因此,如果您没有绑定该方法,您的this 将是undefined。
我注意到虽然 handleSomething 必须手动绑定到这个,
render 和 componentWillMount 没有。方法是否绑定于此
已经?
它们是使用您的类的实例调用的,因此它们已经将this 作为您的实例,而没有使用bind。我想你可以说它已经绑定到this。
为了符号一致性,可以手动绑定吗?
您不需要将 this 与 react 的生命周期方法绑定。如果你真的想,我想你也可以将这些方法绑定到this(可能会有一些我不知道的副作用,因为我并没有真正深入研究它们的源代码),但这是喜欢做obj.handleClick.bind(obj)(); 而不是obj.handleClick();。这是不必要的,并且会花费一些时钟周期做一些不需要的事情。