Class-是对象的模板

定义

class Person {
     constructor() {}
     speak() {}
   }

表达式

const Person = class {
  constructor() {}
  speak() {}
};

调用

new Person();

立即执行

new (class {
    constructor() {
      console.log("cons");
    }
  })();
  // 对比构造函数
  (function () {
    console.log("func");
  })();

类名

首字母大写

构造方法

可不写,浏览器会自动补
实例化时执行构造方法

1)属性/方法定义在构造方法中(实例上)-实例属性/方法,不共享

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
    //定义在构造方法中,各实例方法不共享
    // 各方法有各自地址,占用更多内存
    this.speak = () => {};
  }
}
const zs = new Person("ZS", 18);
const ls = new Person("LS", 20);
console.log(zs.speak === ls.speak); //false

2)属性/方法定义在构造方法外(原型上)-用于赋予对象默认属性值;各实例方法共享

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  // 定义在构造方法外,各实例共享
  speak() {
    console.log("speak");
  }
}
const zs = new Person("ZS", 18);
const ls = new Person("LS", 20);
console.log(zs.speak === ls.speak); //true

与构造函数本质相同

Class

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  // 本质:在原型上添加函数
  speak() {
    console.log("speak");
  }
}

构造函数

function Person(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.speak = function () {
  console.log("speak");
};

属性和方法

实例属性&静态属性

静态就是类的

class Person {
   // 实例属性1:赋给对象默认的属性值
   country = "美国";
   constructor(name) {
   // 实例属性2 
     this.name = name;
   }
   // 静态属性写法1:新提案,注意兼容
   static version = "1.0";
   // 静态属性写法2:方法的返回值形式
   static getVersion() {
     return 1.0;
   }
 }
const p = new Person("Alex");
console.log(p.name); //Alex
console.log(p.country); //美国
console.log(Person.version); //1.0
console.log(Person.getVersion); //ƒ getVersion() { return 1.0;}

实例方法&静态方法

实例方法-实例的方法-通过原型定义-用实例.方法名去调用
静态方法-类的方法-用函数直接定义-用类名.方法名去调用

class Person {
  constructor(name) {
    this.name = name;
  }
  // 实例方法写法1 
  speak() {
    console.log("speak");
    // this指向实例
    console.log(this);
  }
  // 静态方法写法1
  static speak() {
    console.log("人类可以说话");
    // this指向类
    console.log(this);
  }
}
// // 实例方法写法2 
// Person.prototype.speak = function () {
//   console.log("speak");
//   // this指向实例
//   console.log(this);
// };
// 静态方法写法2-不利于类的封装,不建议
// Person.speak = function () {
//   console.log("人类可以说话");
//   // this指向类
//   console.log(this);
// };
const p = new Person("Alex");
console.log(p.name); //Alex
console.log(p.country); //美国
// 调用实例方法
p.speak();
// 调用静态方法
Person.speak();

私有属性&私有方法

一般情况下,类的属性和方法是公开的;可被外界修改,造成意想不到的错误

class Person {
   constructor(name) {
     this.name = name;
   }
 }
 const p = new Person("Alex");
 console.log(p.name); //Alex
 p.name = "ZS";
 console.log(p.name); //ZS

ES6原生中无私有属性/方法,需要模拟
方法一:_开头

class Person {
  constructor(name) {
    this._name = name;
  }
  // 访问接口
  getName() {
    return this._name;
  }
}
const p = new Person("Alex");
console.log(p.getName()); //Alex
p.name = "ZS";
console.log(p.getName()); //Alex

方法二:利用IIFE特性(可形成单独作用域)
相较于方法一,私有性更强

// 封装
(function () {
  // 被移出的类
  let username = "";
  class Person {
    constructor(name) {
      username = name;
    }
    // 访问接口
    getName() {
      return username;
    }
  }
  //在全局中复制一个Person类
  window.Person = Person;
})();
// 调用
(function () {
  const p = new Person("Alex");
  console.log(p.getName()); //Alex
  p.name = "ZS";
  console.log(p.getName()); //Alex
})();

继承

extends

继承父类所有方法和属性
同名覆盖原则-改写方法和属性
增加自有方法和属性

class Person {
  constructor(name, sex) {
    // 实例属性
    this.name = name;
    this.sex = sex;
    // 实例方法-不共享
    this.say = function () {
      console.log("speak1");
    };
  }
  //  实例方法-共享
  speak() {
    console.log("speak2");
  }
  // 静态方法
  static speak() {
    console.log("static speak");
  }
}
// 静态属性
Person.version = "1.0";
class Programmer extends Person {
  // 子类增加属性:feature
  constructor(name, sex, feature) {
    super(name, sex);
    // this不可在super之前
    this.feature = feature;
  }
  // 子类方法改写:同名覆盖
  speak() {
    console.log("speak2new");
  }
}
// 子类属性改写:同名覆盖
Programmer.version = "2.0";

super

作为函数

代表父类的构造方法,只能用于子类的构造方法,用于其他地方报错
虽代表父类的构造方法,但内部的this指向子类的实例

class Person {
  constructor(name) {
    this.name = name;
    console.log(this); //Programmer {name: undefined}
  }
}
class Programmer extends Person {
  constructor(name, sex) {
    super(name);
    this.sex = sex;
    console.log(this); 
    //Programmer {name: undefined, sex: undefined}
  }
  hi() {
    // super();//报错
  }
}
new Programmer();

作为对象-用于构造方法中

代表父类原型对象,Person.prototype;故定义在父类实例上的方法或属性,无法通过super调用
用super调用父类原型上的方法时,方法内部this指向当前的子类实例

class Person {
  constructor(name) {
    // 定义在父类实例上的属性
    this.name = name;
  }
  // 定义在父类原型上的属性
  speak() {
    console.log("speak");// speak
    console.log(this); //Programmer {name: 'ZS', sex: 'male'}
  }
}
class Programmer extends Person {
  constructor(name, sex) {
    super(name);
    this.sex = sex;
    // super不可访问定义在父类实例上的属性;
    console.log(super.name); //undefined
    // super可访问定义在父类原型上的属性
    super.speak(); 
  }
}
new Programmer("ZS", "male");

作为对象-用于一般方法中(特点同构造方法)

代表父类原型对象Person.prototype;
故定义在父类实例上的方法或属性,无法通过super调用
用super调用父类原型上的方法时,方法内部this指向当前的子类实例

class Person {
      constructor(name) {
        this.name = name;
      }
      speak() {
        console.log("speak"); //speak(输出2)
        console.log(this); 
        //Programmer {name: 'ZS', sex: 'male'}(输出3)
      }
    }
    class Programmer extends Person {
      constructor(name, sex) {
        super(name);
        this.sex = sex;
      }
      speak() {
        // super不可访问定义在父类实例上的属性;
        console.log(super.name); //undefined(输出1)
        // super可访问定义在父类原型上的方法
        // 1)先继承父类的speak()内容
        super.speak();
        // 2)再写子类的speak()内容
        console.log("Programmer speak"); 
        //Programmer speak(输出4)
      }
    }
    const p = new Programmer("ZS", "male");
    p.speak();

作为对象-用于静态方法中-报错

静态方法里只能调用静态方法、只能使用静态属性
代表父类,而不是父类原型
用super调用父类原型上的方法时,方法内部this指向当前的子类

class Person {
  constructor(name) {
    this.name = name;
  }
  static speak() {
    console.log("Person speak"); //Person speak
    console.log(this); //class Programmer extends Person {...}
  }
}
class Programmer extends Person {
  constructor(name, sex) {
    super(name);
    this.sex = sex;
  }
  static speak() {
    super.speak();
    console.log("Programmer speak"); //Programmer speak
  }
}
Programmer.speak();

显式指定作为函数还是对象,否则报错

class Person {
   constructor(name) {
     this.name = name;
   }
   speak() {
     console.log("speak");
   }
 }
 class Programmer extends Person {
   constructor(name, sex) {
     // 显示指定-作为函数用
     super(name);
     this.sex = sex;
     // 不指定报错
     // console.log(super);
     // 显示指定-作为对象用
     console.log(super.speak);
   }
 }

应用-幻灯片

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值