Class

概览

  • 类的基本语法
  • 类的继承
  • 类的实例
  • es5 下的面向对象

类的基本语法

  • 构造方法 实例属性 实例方法(普通 generator 方法 setter getter async)静态属性 静态方法 私有属性 私有方法
 1class People {
 2    constructor(name,age,sex) {
 3        this.name = name;
 4        this.age= age;
 5        this.sex= sex;
 6    }
 7}
 8//类里面的成员方法与属性都采用小驼峰
 9class Boy extends People {
10    constructor(name,age) {
11        super(name,age,'男');
12    }
13
14    /*私有属性与私有方法在属性或方法上加#,只能在类内部使用 私有属性和私有方法前面,也可以加上static关键字,
15    表示这是一个静态的私有属性或私有方法 私有只是提案,现有chrome已经实现,见1.1*/
16    #a;
17    #b=3;
18    static #c= 4;
19    static #m(){}
20    #parseName(){
21        return this.name.replace(/\s/g,'');
22    }
23
24    //实例属性的另外一种写法 一种是constructor中this.x
25    money;
26    money= 1000;
27
28    //静态属性 通过类访问
29    static maxAge= 120;//见1.2
30
31    //getter
32    get age(){
33        retun this.age+1;//见1.4
34    }
35    //setter
36    set age(value){
37        this.age= Math.floor(value);
38        //setter方法在对象中(非类)需要注意 可能内存溢出,见1.3
39    }
40
41    //静态方法 不能访问实例属性与方法
42    static getMaxAge(){
43        return Boy.maxAge;
44    }
45    getAge(){
46        return this.age+this.#b;
47    }
48
49    //generator方法
50    *getName(){
51        yield Promise.resolve(1);
52        yield Promise.resolve(2);
53    }
54
55    //异步函数 串行执行 比如获取了用户的银行余额 再去付款
56    async serial(){
57        let b= await Promise.resolve(1);//返回值,不是promise
58        let c= await Promise.resolve(b);
59        return c; //返回promise包装
60    }
61
62    //静态方法 自我实现四舍五入
63    static round(value){
64        if(typeof value ==='number'){
65            return (Number.parseInt(value)+.5>value)?Number.parseInt(value):(Number.parseInt(value)+1)
66        }else{
67            return 0;
68        }
69    }
70}
 1//1.1
 2class PrivateVar{
 3    #a=2;
 4    b=3;
 5    getA(){
 6        return this.#a;
 7    }
 8}
 9var p1= new PrivateVar();
10console.log(p1.#a);//报错
11console.log(p1.b);//3
12console.log(p1.getA());//2
 1//1.2
 2class Static1{
 3    static width= 200;
 4    height= 100;
 5    static getArea(){
 6        //错误写法 静态不能访问非静态属性
 7        return Static1.width*this.height;
 8    }
 9    getMaxSide(){
10        //非静态方法可以访问静态属性
11        return Math.max(Static1.width,this.height);
12    }
13}
14let s1= new Static1();
15s1.getMaxSide();
16Static1.gettArea();
17/*NaN (一个数字与undefined相加=NaN,null+数字=数字,字符串+数字=字符串拼接,true+1=2,false+1=1,对象+1=1)
18转化优先级undefined,null,boolean=>number=>string,
191.任何与字符串相加都是字符串
202.其它相加先转化为数字,undefined=》NaN,null=>0
213.NaN与其它数字相加等于NaN*/
 1//1.3
 2let user = {
 3  name: 'xx'.
 4  get name() {
 5    return this.name;
 6  },
 7  set name(value) {
 8    this.name = value //这句话报错了
 9  }
10};
11user.name = "Peter"; //尝试赋值的时候报错Uncaught RangeError: Maximum call stack size exceeded
12//解决方法
13let user = {
14  _name:'xx',
15  get name() {
16    return this._name;
17  },
18  set name(value) {
19    this._name = value //设置一个中转变量
20  }
21};
1//1.4
2class SetVar{
3    m=2;
4    set m(d){this.m=d}
5}
6let d=new SetVar();
7d.m=99;//{m:99}
  • 类方法之间不需要逗号分隔,加了会报错
  • 类的内部所有定义的方法,都是不可枚举的(non-enumerable)。
1class Point {
2  constructor(x, y) {
3    // ...
4  }
5  toString() {
6    // ...
7  }
8}
9Object.keys(Point.prototype)// []
  • 类与模块为严格模式,不需要声明 use strict;
  • 类必须使用 new 调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用 new 也可以执行。
1function m(){console.log(new.target===m)}
2m()//false
3new m()// true  通过这个可以强制函数通过new来调用
  • 类不存在变量提升(hoist),这一点与 ES5 完全不同。
1new Foo(); // ReferenceError
2class Foo {}
  • 方法多层嵌套,this 指向问题解决
11.箭头函数
22.重新赋值 如 let _t= this;
33.绑定this指向
4class Logger {
5  constructor() {
6    this.printName = this.printName.bind(this);
7  }
8  // ...
9}
  • 类名采用大驼峰命名(单词首字母大写)

类的继承

  • 类继承使用 extends 关键字
  • super() 可以调用父类的构造方法(可以传递非默认参数)
  • 如果没有显式指定构造方法,则会添加默认的 constructor 方法。不显式调用会默认调用父类的构造方法
 1基类默认构造方法
 2constructor() {}
 3派生类,默认构造函数
 4constructor(...args) {
 5  super(...args);
 6}
 7//-------
 8class A {constructor(a){this.a=a;}};
 9class B extends A{}
10new B(1)//{a:1}
  • 派生类可以继承父类的属性与方法

类的实例化

  • 调用 new 类名(参数a,b...),实际执行 constructor 构造方法,接收参数,实例化一个实例对象
  • 类的所有实例共享一个原型对象 类名.prototype
  • 继承与覆盖
 1class A {
 2    x=1;
 3    y(){}
 4    z(){console.log('a')}
 5}
 6class B extends A{
 7    constructor(a){if(a){this.m=a;}}
 8    m=2;
 9    z(){console.log('b')}
10}
11let p= new B(9);//m值=9;
12p.z();//'b' 覆盖了父类的z方法
13let p1= new B();// m值=2

es5 下的面向对象

  • 生成实例对象的传统方法是通过构造函数 ES6 的 class 可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到, 新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已
 1function Point(x, y) {
 2  this.x = x;
 3  this.y = y;
 4}
 5
 6Point.prototype.toString = function () {
 7  return '(' + this.x + ', ' + this.y + ')';
 8};
 9
10var p = new Point(1, 2);
  • ES6 的类,完全可以看作构造函数的另一种写法。
1class Point {
2  // ...
3}
4
5typeof Point // "function" 类的数据类型就是函数
6Point === Point.prototype.constructor // true 类本身就指向构造函数
  • 类有 prototype 和proto ,对象实例只有proto
1function Foo(){}
2let p= new Foo();
3/*
4p.__proto__===>Foo.prototype(其__proto__===>Object.prototype(其__proto__===>null))
5Foo.prototype,Object.prototype,Function.prototype都是由构造函数创建的
6自定义构造方法的__proto__=>Function.prototype(其__proto__==>Object.prototype)
7见github 图
8*/

Event
Date

评论