在读这篇文字之前建议先理解JavaScript中作用域链的概念,戳这里:JavaScript中的执行环境、作用域链和闭包详解,以及理解JavaScript中的this关键字,戳这里:JavaScript中的this关键字如何理解
原生的JavaScript中只有对象,没有类的概念。其对象是基于原型链实现的。
如果要生成一个对象实例,需要先定义一个构造函数,然后通过new操作符来完成。构造函数示例:
//函数名和实例化构造名相同且大写
function Person(name,age) {
this.name = name;
this.age=age;
}
Person.prototype.say = function(){
return "我的名字叫" + this.name+"今年"+this.age+"岁了";
}
var obj=new Person("laotie",88);//通过构造函数创建对象,必须使用new 运算符
console.log(obj.say());//我的名字叫laotie今年88岁了
构造函数生成实例的执行过程:
- 当使用了构造函数,并且new 构造函数(),后台会隐式执行new Object()创建对象;
- 将构造函数的作用域给新对象,(即new Object()创建出的对象),而函数体内的this就代表new Object()出来的对象。
- 执行构造函数的代码。
- 返回新对象(后台直接返回);
ES6引入了Class(类)这个关键词,使得JavaScript的对象更像面向对象的语言,但实际上class定义的依旧是函数(typeof 输出的是function类型)。
改写之前的代码:
class Person{//定义了一个名字为Person的类
//constructor是一个构造方法,用来接收初始化参数,通过new命令生成对象实例时,自动调用该方法。
constructor(name,age){
this.name = name;//this代表的是实例对象
this.age=age;
}
say(){//这是一个类的方法,注意千万不要加上function
return "我的名字叫" + this.name+"今年"+this.age+"岁了";
}
}
var obj=new Person("laotie",88);
console.log(obj.say());//我的名字叫laotie今年88岁了
React 组件
现在来看React菜鸟教程中的React 组件这一节。这就明白了为什么可以通过这两种方式定义组件。
React 组件中的this关键字
在React菜鸟教程React 事件处理这一节,有这样一段代码:
为了更方便理解this这个关键字,以React菜鸟教程React 表单与事件这一节中的一个实例为例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 实例</title>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
class Content extends React.Component {
render() {
return <div>
<input type="text" value={this.props.myDataProp} onChange={this.props.updateStateProp} />
<h4>{this.props.myDataProp}</h4>
</div>;
}
}
class HelloMessage extends React.Component {
constructor(props) {
super(props);
this.state = {value: 'Hello Runoob!'};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
render() {
var value = this.state.value;
return <div>
<Content myDataProp = {value}
updateStateProp = {this.handleChange}></Content>
</div>;
}
}
ReactDOM.render(
<HelloMessage />,
document.getElementById('example')
);
</script>
</body>
</html>
现在改写script代码如下(就是打印了一些值出来):
class Content extends React.Component {
render() {
return <div>
<input type="text" value={this.props.myDataProp} onChange={this.props.updateStateProp}/>
<h4>{this.props.myDataProp}</h4>
</div>
}
}
class HelloMessage extends React.Component {
constructor(props) {
super(props);
console.log(`In HelloMessage---------`);
console.log(this);
console.log(typeof this);
console.log(typeof HelloMessage);
console.log(this.handleChange);
console.log(typeof this.handleChange);
console.log(`End HelloMessage---------`);
this.state = {value: 'hello Runoob!'};
// this.handleChange();
// this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
console.log("In handleChange------------");
console.log(typeof this);
console.log(this);
console.log("End handleChange------------");
// this.setState({value:event.target.value});
}
render() {
var value = this.state.value;
return <div>
<Content myDataProp = {value}
updateStateProp = {this.handleChange}>
</Content>
</div>
}
}
console.log(`%%%%%%%%%%%%%%%%%%%%%%%%%%${typeof HelloMessage}`);
ReactDOM.render(
<HelloMessage />,
document.getElementById('example')
);
结果如下,可以得出结论:HelloMessage是函数,this关键词指向函数所在的当前对象,也就是this把HelloMessage当做对象来看待,可以调用HelloMessage中定义的函数。
现在在输入框中输入字符(没有显示),但是可以调用到在Content中为输入框定义的onChange事件,结果如下,说明handleChange中的this并没有指向某个对象,handleChange只是作为一个普通的函数,this值为undefined。
现在把构造函数中的this.handleChange();语句注释去掉,结果如下,此时handleChange作为
HelloMessage的方法调用,this自然就指向了调用该方法的对象。因此在构造函数中需要加上this.handleChange = this.handleChange.bind(this);这一句,为handleChange绑定一个this。
参考:
https://www.jianshu.com/p/86267fab4878