class 可以理解为构造函数的语法糖。
关于这篇主要掌握相关的语法,最重要的是使用场景。

1、class创建

  1. class ClassSelf {
  2. constructor(name,age,lang){
  3. this.name = name;
  4. this.age = age;
  5. this.lang = lang;
  6. this.a = 11;
  7. this.shot = function(){
  8. console.log('constructor',this.lang)
  9. }
  10. }
  11. shout(){
  12. console.log(this.lang)
  13. }
  14. }
  15. const cat = new ClassSelf('大咪',2,'喵喵');

cat值:
image.png
仅对于class ClassSelf 来说:

  1. constructor方法不用加function,且直接定义在了类的prototype里。
  2. 类的prototype不可枚举的( diff1:但构造函数是可以的)

    1. console.log('ClassSelf1:'Object.keys(ClassSelf.prototype))
    2. console.log('ClassSelf2:', Object.getOwnPropertyNames(ClassSelf.prototype))

    image.png
    关于可枚举可简单理解为:Object.keys()可枚举构造函数的prototype,不可枚举class里的函数(虽说也是直接添加到了class的prototype里),但可枚举通过prototype、proto添加的属性。Object.getOwnPropertyNames()无论构造函数还是类都可以取出来

  3. 可直接给类原型添加新方法

    1. Object.assign(ClassSelf.prototype,{sleep(){}})

    image.png

    2、constructor

  4. 是类的默认方法,一个类必须有一个constructor()方法。如果没有显示定义,一个空的constructor()方法会被默认添加。

  5. constructor默认返回实例对象(this),也可指定返回其他对象

    1. constructor(name,age,lang){
    2. this.name = name;
    3. this.age = age;
    4. this.lang = lang;
    5. this.a = 11;
    6. this.shot = function(){
    7. console.log('constructor',this.lang)
    8. }
    9. return {
    10. test:1
    11. }
    12. }

    image.png

  6. 在使用 new生成实例时,会自动调用 constructor函数。

    3、类的实例

  7. 类必须使用 new 命令生成实例对象,否则报错。( diff2:但构造函数可以不用new,构造函数可以当作普通函数,类不可以)。

  8. 实例的属性 除非显示定义在本身(即定义在this对象上),否则都是定义在原型上。

❓❎此处存疑:定义在this外的常量也在实例的属性上
解疑:constructor同级的属性 也是实例属性。

  1. class ClassSelf {
  2. constructor(name,age,lang){
  3. this.name = name;
  4. this.age = age;
  5. this.lang = lang;
  6. this.a = 11;
  7. this.shot = function(){
  8. console.log('constructor',this.lang)
  9. }
  10. }
  11. b = 2; //!!!!!!!
  12. shout(){
  13. console.log(this.lang)
  14. }
  15. }
  16. const cat = new ClassSelf('大咪',2,'喵喵');
  17. console.log('cat: ',cat)
  18. console.log('cat Property: ',Object.getOwnPropertyNames(cat))
  19. console.log(cat.hasOwnProperty('b'))

image.png

  1. 所有的实例共享一个原型。使用proto可改写原型 ```javascript const cat = new ClassSelf(‘大咪’,2,’喵喵’); const cat1 = new ClassSelf(‘小咪’,22,’喵喵喵喵’)

cat.proto.say = function(){ console.log(‘say:’,this.name) } cat1.say()

  1. <a name="p6kTo"></a>
  2. ### ![image.png](https://cdn.nlark.com/yuque/0/2022/png/1398967/1651029729054-7144fcb2-9588-4b45-9da2-e3444ce028ee.png#clientId=u463176de-e72e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=221&id=u91eb06fc&margin=%5Bobject%20Object%5D&name=image.png&originHeight=442&originWidth=1404&originalType=binary&ratio=1&rotation=0&showTitle=false&size=162613&status=done&style=none&taskId=u31ed5701-0ce6-4336-b1e0-e7f833c6f7e&title=&width=702)
  3. <a name="dCcKe"></a>
  4. ### 4 、get set
  5. 对某个属性设置存值函数和取值函数,拦截该属性的存取行为。<br />官方解释如上,个人觉得是有点坑的,因为不小心就会会错意。<br />怎么滴个用法呢,如下。
  6. ```javascript
  7. class ClassSelf {
  8. constructor(name,age,lang){
  9. this.age = age;
  10. }
  11. get _age(){
  12. return this.age + 'get'
  13. }
  14. set _age(value){
  15. this.age = value+"set"
  16. // this._age = value+"set" 报错 Uncaught RangeError: Maximum call stack size exceeded
  17. }
  18. }
  19. const cat = new ClassSelf('大咪',2,'喵喵');

image.png

  1. cat._age = 888

image.png

  1. 间接改变改变值,可以实现数据绑定。
  2. 通过get定义的属性,只要用户访问该属性就会触发这个get。通过set定义的属性,只要用户修改该属性的值,就会触发set。

❌下述写法会报错

  1. class ClassSelf {
  2. constructor(name,age,lang){
  3. this.age = age;
  4. }
  5. get age(){
  6. return this.age + 'get'
  7. }
  8. set age(value){
  9. this.age = value + 'set'
  10. // return value + 'set' 或者这样
  11. }
  12. }

5、this

。。。待续

实例属性

  1. 定义在constructor()方法里面的this上面;
  2. 定义在类的最顶层

好处:看上去比较整洁

  1. class ClassSelf {
  2. constructor(name,age,lang){
  3. //this上的都是实例属性
  4. this.name = name;
  5. this.age = age;
  6. this.lang = lang;
  7. this.a = 11;
  8. this.shot = function(){
  9. console.log('constructor',this.lang)
  10. }
  11. }
  12. b = 2; //实例属性
  13. }

静态方法

如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。

  1. class ClassSelf {
  2. constructor(name,age,lang){
  3. this.age = age;
  4. this.name = name;
  5. this.a = 11;
  6. }
  7. static see(){
  8. // console.log('a:',this.a)
  9. // console.log('name:',this.name)
  10. console.log('what do you look!')
  11. }
  12. }
  13. ClassSelf.see() //'what do you look!'
  14. cat.see() //报错:Uncaught TypeError: cat.see is not a function
  1. 关于静态方法里的this:指的是类,而不是实例。
    image.png
  2. 静态方法和非静态方法可以重名。
  3. 父类的静态方法可以被子类继承。

    静态属性

    静态属性指的是 Class 本身的属性,即class.propName,而不是定义在实例对象(this)上的属性。 ```javascript class ClassSelf {

    static s = ‘see’ //es6后的提案写法 }

ClassSelf.s = ‘see’;

  1. <a name="Fa1Mq"></a>
  2. ### 私有方法、私有属性
  3. 私有方法和私有属性,是只能在类的内部访问的方法和属性,外部不能访问。<br />(ES6 不提供,只能通过变通方法模拟实现)<br />变通方法:
  4. ```javascript
  5. //方法3:利用Symbol值的唯一性,将私有方法的名字命名为一个Symbol值
  6. const bar = Symbol('bar');
  7. const snaf = Symbol('snaf');
  8. class ClassSelf {
  9. // 公有方法
  10. foo (baz) {
  11. this._bar(baz);
  12. }
  13. // 私有方法
  14. //方法1:在命名上加以区别,不保险,在类的外部也可以调用
  15. _bar(baz) {
  16. return this.snaf = baz;
  17. }
  18. //方法2:私有方法移出类
  19. foo (baz) {
  20. bar.call(this, baz);
  21. }
  22. foo(baz) {//方法3:
  23. this[bar](baz);
  24. }
  25. [bar](baz) {// 私有方法
  26. return this[snaf] = baz;
  27. }
  28. //提案:方法是在属性名之前,使用#表示
  29. #count = 0;
  30. }
  31. //方法2:
  32. function bar(baz) {
  33. return this.snaf = baz;
  34. }

关于继承

使用场景