Blake Blake - 9 days ago 8
Javascript Question

When bind is not set, why `this` is not referring to the window object?

I am wondering why if I modify this line

{this.increaseQty.bind(this)}
to
{this.increaseQty}
, the console prompts Uncaught TypeError: Cannot read property 'setState' of undefined instead of Uncaught TypeError: this.setState is not a function(…) ?? If the bind is not set, shouldn't
this
be the window object ?

export default class CartItem extends React.Component {
constructor(props) {
super(props);
this.state = {
qty: props.initialQty,
total: 0
};
}
componentWillMount() {
this.recalculateTotal();
}
increaseQty() {
this.setState({qty: this.state.qty + 1}, this.recalculateTotal);
}
decreaseQty() {
let newQty = this.state.qty > 0 ? this.state.qty - 1 : 0;
this.setState({qty: newQty}, this.recalculateTotal);
}
recalculateTotal() {
this.setState({total: this.state.qty * this.props.price});
}
render() {
return <article className="row large-4">
<figure className="text-center">
<p>
<img src={this.props.image}/>
</p>
<figcaption>
<h2>{this.props.title}</h2>
</figcaption>
</figure>
<p className="large-4 column"><strong>Quantity: {this.state.qty}</strong></p>

<p className="large-4 column">
<button onClick={this.increaseQty.bind(this)} className="button success">+</button>
<button onClick={this.decreaseQty.bind(this)} className="button alert">-</button>
</p>

<p className="large-4 column"><strong>Price per item:</strong> ${this.props.price}</p>

<h3 className="large-12 column text-center">
Total: ${this.state.total}
</h3>

</article>;
}
}

Answer

If you don't invoke a function as a method (and it is not bound, and you are not using call or apply), then the value of this inside the function will be undefined IF:

  • you are in strict mode
  • you are in ES2015 (strict mode is on by default)

Otherwise it will be the global object.

Also, note that some host objects (e.g. setTimeout) have their own specific behavior for defining the this value used when, for example, callbacks are invoked.