js面向对象编程

基本概念:原型链、继承

class Person {
  // 这里定义固定的属性,该属性定义在每一个new出来的对象上面
  canSpeak = true;
  canSleep = true;
  toFuck = ()=>{
    // 箭头函数中的this会自动向外层寻找,外层的this指向的就是该实例(此处使用function则不行)
    if( this.canSleep == true ){
      this.speak();
    }else{
      return 
    }
  };
  // static关键字的使用使得defaultProps定义在了该类的原型对象上面,而不是存在于实例对象上,注意与上面的属性定义方式相区分
  static defaultProps = {
    sex: '男',
    age: 18
  }
  // 定义构造器,传入参数
  constructor(name,age){
    this.name = name;
    this.age = age;
  }
  // 思考: speak对象放在了哪里? ----类的原型对象(prototype)上(实例对象上面没有),供实例使用。
  speak(){
    console.log(`I am ${this.name}, ${this.age} years old.`);
  }

}

// 继承
class Student extends Person {
  // constructor也可以不写,如果写了就必须有super来继承父亲的属性
  constructor(name,age,grade){
    super(name,age); // 如果是继承,则必须有super继承父类当中的属性
    this.grade = grade;
  }
  speak(){
    console.log('重写了父类继承过来的方法!')
  }
  study(){
    // 思考🤔  : study方法放在了哪里? --类的原型对象上,供实例使用
    console.log('studying...');
  }
}

// Instantiation
let p1 = new Person('Jone', 18);
let p2 = new Student('Mary',16, 3); // 如果调用了子类中的不存在方法,会顺着原型链查找,查找父亲节点有没有。
p1.speak();
p2.speak();

一些函数:

  1. call()函数
// p1.speak.call(someObject) // call()可以更改某个类的方法的this对象
  1. apply()函数
  2. bind()函数
// 改变某函数/对象方法的this指向(将函数绑定到某个对象上面)
function demo(){
  console.log(this);
}
demo(); // output: window object
const x = demo.bind({a:1, b:2});
x(); // output : {a:1 , b:2}

典型问题

  1. 方法中的this
    方法中调用this时候,通常情况下,调用的是实例对象,通俗来讲就是new出来的返回值。但是有一种情况,就是当我在另一个方法中调用本方法时候,这时候的this就不一定指向实例对象了!
    来看一个react组件:
// create component
class Weather extends React.Component{
  constructor(props){
    super(props)
    this.state = { isHot: false }
  }
  render(){
    // 读取状态
    const {isHot} = this.state;
    return <h1 onClick={this.changeWeather}> 今天天气很{isHot?'炎热':'凉爽'}</h1>
  }
  changeWeather(){
    // 我先检查下this对象
    console.log(this);      // ----> undefined
    this.state.isHot = !this.state.isHot;
  }
}

ReactDOM.render(<Weather/>, document.getElementById('test'))

注意: 类中的方法默认开启了局部的严格模式, this默认不是window而是undefined

通过上面的例子可以看出,这时候的调用仅仅是执行了计算机内存"堆"中的一个函数(这个函数是作为一个方法的),这时候不一样的地方就是我们进行了直接调用,没有通过实例调用方法的形式调用。所以该方法内的this就没有对象给它了,值为undefined


解决办法:

// create component
class Weather extends React.Component{
  constructor(props){
    super(props);
    this.state = { isHot: false };
    // 在实例化(new Weather)的时候,执行constructor函数,将对象上面的`changeWeather`方法绑定this对象,
    // 然后在将该方法绑定到该对象(已经实例化)的`myChangeWeather`属性上面去(或者说给到了实例本身)
    // 那么当我在调用的时候,是不是调用的是一个属性方法,而不是原形链上的方法。该属性方法能够直接获取this了(因为已经绑定了)
    this.myChangeWeather = this.changeWeather.bind(this);
  }
  render(){
    // 读取状态
    const {isHot} = this.state;
    return <h1 onClick={this.myChangeWeather}> 今天天气很{isHot?'炎热':'凉爽'}</h1>
  }
  changeWeather(){
    // 我先检查下this对象
    console.log(this);
    this.setState({isHot: !isHot}); // diff后合并更新状态
  }
}

ReactDOM.render(<Weather/>, document.getElementById('test'))


posted @ 2021-06-02 19:11  Bravo_Jack  阅读(50)  评论(0编辑  收藏  举报