概览
- 类的基本语法
- 类的继承
- 类的实例
- 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 {}
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);
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*/
评论