调用 ES6 方法时的绑定上下文.如何从称为回调的方法中访问对象
Binding context when calling ES6 method. How to access object from within method called as callback?
我正在尝试围绕ES6中类的语法进行思考。同时通过Bonnie Eisenman的Learning React Native学习Fabric原生。
我遇到了一个关于在回调中访问this
的问题,当该回调是一个类"方法"时。我知道回调中有关词汇this
的问题已经在 StackOverflow 上多次提出。例如在如何在回调中访问正确的"this"上下文?
根据我在网上的研究,我遇到了一个解决方案。但我不确定这是在 ES6 中执行此操作的正确方法。
当我尝试以下操作时,我的问题出现了:
class WeatherProject extends Component {
constructor(props) {
super(props);
this.state = {
zip: ''
};
}
_handleTextChange(event) {
console.log(event.nativeEvent.text);
this.setState({zip: event.nativeEvent.text})
}
render() {
return (
<TextInput
style={styles.input}
onSubmitEditing={this._handleTextChange}/>
);
}
}
(我只是对书中的示例进行了轻微修改,以匹配 ES6 类语法和导入/导出语法而不是 Require。
如果我这样做,_handleTextChange
中的this
是未定义的(无法读取未定义的属性"setState")。我对此感到惊讶。来自其他 OO 语言,我的解释好像这种方法的行为更像是一个静态方法。
我已经能够通过跳过类方法并使用箭头符号来解决这个问题。 onSubmitEditing={event => this.setState({name: event.nativeEvent.text})}
.哪个工作正常。我对此没有任何问题或困惑。
不过,我真的很想弄清楚如何调用类方法。经过相当多的研究,我设法通过执行以下操作使其工作:onSubmitEditing={this._handleTextChange.bind(this)}
.也许我误解了JavaScript的一个基本方面(我是JS的初学者),但这对我来说似乎完全是疯狂的。真的没有办法在不显式绑定对象的情况下从方法中访问对象的上下文......这是自己的方法,在它被称为的地方?
我还尝试在构造函数中添加var self = this;
并在_handleTextChange
中调用self.setState
。但发现这不起作用并不太惊讶。
当对象作为回调调用时,从其方法之一访问对象的正确方法是什么?
React.createClass (ES5) 创建类的方式有一个内置功能,可以将所有方法绑定到自动this
。但是在 ES6 中引入 classes
并迁移 React.createClass 时,他们发现对于不习惯其他类中此功能的 JavaScript 开发人员来说,这可能会有点令人困惑,或者当他们从 React 迁移到其他类时可能会感到困惑。
因此,他们决定不将其内置到 React 的类模型中。如果你愿意,你仍然可以在构造函数中显式预绑定方法,如果你愿意
class WeatherProject extends Component {
constructor(props) {
super(props);
this.state = {
zip: ''
};
this._handleTextChange = this._handleTextChange.bind(this); //Binding to `this`
}
_handleTextChange(event) {
console.log(event.nativeEvent.text);
this.setState({zip: event.nativeEvent.text})
}
但是我们总是有一个简单的方法来避免这种预绑定。是的!没问题。箭头函数。
class WeatherProject extends Component {
constructor(props) {
super(props);
this.state = {
zip: ''
};
}
_handleTextChange = event => {
console.log(event.nativeEvent.text);
this.setState({zip: event.nativeEvent.text})
}
render() {
return (
<TextInput
style={styles.input}
onSubmitEditing={this._handleTextChange}/>
);
}
}
顺便说一句,这都是关于反应的。ES6 类始终具有从方法内部访问对象上下文的方法,而无需将对象显式绑定回其自己的方法。
class bindTesting {
constructor() {
this.demo = 'Check 1';
}
someMethod() {
console.log(this.demo);
}
callMe() {
this.someMethod();
}
}
let x = new bindTesting();
x.callMe(); //Prints 'Check 1';
但是,如果我们在 JSX 表达式中调用它,这不会打印"Check 1"。
编辑 :: 正如@Oka提到的,类体中的箭头函数是 ES7+ 功能,在 babel 等编译器/填充物中可用。如果你没有使用支持此功能的转译器,我们可以如上所述绑定到this
或像这样编写一个新的 BaseComponent(这是一个坏主意)
class BaseComponent extends React.Component {
_bind(...methods) {
methods.forEach( (method) => this[method] = this[method].bind(this) );
}
}
class ExampleComponent extends BaseComponent {
constructor() {
super();
this._bind('_handleTextChange', '_handleClick');
}
// ...
}
也许我误解了JavaScript的一个基本方面(我是JS的初学者),但这对我来说似乎完全是疯狂的。真的没有办法在不显式绑定对象的情况下从方法中访问对象的上下文......这是自己的方法,在它被称为的地方?
好吧,"方法"不是由javascript中的对象拥有的。所有函数都是一等值(对象),而不是对象或类的"部分"。
this
值的绑定在调用函数时发生,具体取决于函数的调用方式。具有方法表示法的函数调用将其this
设置为接收对象,事件侦听器调用将其this
设置为当前事件目标,普通函数调用仅具有undefined
。
如果要访问实例上的方法,则实际上只是标准原型继承属性访问,它生成一个函数,然后调用该函数并将其动态绑定到接收器。
如果要在实例上调用函数作为事件侦听器的方法,则需要显式创建一个执行此操作的函数 - "bound"方法。在 ES6 中,通常首选箭头符号。
ES6 和 React 暂时,在常规的旧 JavaScript 中,当你传递一个对象的方法时,它只是对函数本身的引用,而不是对象和函数。
任何调用函数都可以选择使用隐式this
,通过正常调用函数,甚至可以选择使用.call
和.apply
或.bind
来更改上下文。
var O = {
foo: function () {
console.log(this);
},
bar: 51
};
O.foo(); // `this` is O, the implicit context, inferred from the object host
var foo = O.foo;
foo(); // `this` is is the global object, or undefined in Strict Mode
正在发生的事情是,您正在将_handleTextChange
函数传递给事件发射器,该事件发射器将在一段时间后执行。事件发射器不知道它接收了作为方法的函数。它只是执行它。
var O = {
foo: function (event) {
console.log(this);
console.log(event);
},
bar: 51
};
function invoke (func) { // the function reference held by O.foo is now held by `func`
func('some param'); // it has no idea as to what the contextual `this` is bound to, maybe its implicitly global, maybe its explicitly bound, maybe its undefined
}
invoke(O.foo);
invoke(O.foo.bind(O)); // A copy of the function with the context explicitly bound
看看上下文共享:
function foo () {
console.log(this.a);
}
// Both object hold references to the foo function
var O = { foo : foo, a : 5 },
O2 = { bar : foo, a : 1 };
O.foo(); // implicit `this` from O
O2.bar(); // implicit `this` from O2
var Z = { a : 23 };
O.foo.call(Z); // explicit `this` from Z
这些例子可能会变得任意复杂。
- Google Data API上的OOP Javascript回调方法
- 有没有什么方法可以停止Jquery中的animate(也可以停止完整的回调函数)
- 对中的函数调用进行排序是回调的唯一方法
- Javascript:对回调创建的对象执行方法
- 如何向.apply()方法添加回调
- 在 Javascript 中实现解耦代码/回调的正确方法是什么?
- 一种在应用.appendTo()方法时使用回调函数的方法
- 与 promise 一起使用时,异步瀑布不执行下一个回调方法
- 从类方法中的 ajax post 函数回调函数更改 javascript 类属性
- 如何将回调函数添加到 .map 方法
- 传递promise回调方法的更好方法
- 将类方法绑定到类外绑定的事件处理程序内的AJAX成功回调
- 将方法作为回调传递
- Node.JS:类方法作为回调
- 将参数传递给 Ressource 的方法回调
- 从 javascript 对象方法回调中检索变量
- javascript设计模式-通过公共方法回调
- 如何在Nodejs中模拟外部依赖方法回调参数
- Javascript数组映射方法回调参数
- iCheck on()方法回调不起作用