class
class是一种语法糖,其实就是构造函数及其原型的另一种写法,本质上是函数,换种写法提高可读性和维护性。
语法:
声明:不可提升,必须要new才可以执行
class Person {} // 函数声明
let Person = class{} // 函数表达式
new Person() // 执行
方法私有化
私有属性就是在构造器上通过this绑定的属性,公有属性的方法是原型上的方法
直接在class函数内部声明一个变量,会自动挂载到构造函数上,还是私有属性
class Person{
a = 1;
}
new Person();
会自动变成
class Person{
constructor(){
this.a = 1;
}
}
一般来说属性都在构造器里私有,方法都是公有的
要想让公有方法私密化(公有属性的私有方法),方案如下:
法1. Symbol
const eat = Symbol();
class Person{
constructor(name, age){
this.name = name;
this.age = age;
}
say(){
console.log(1);
}
[eat](){
console.log('I can eat');
}
}
console.log(new Person().eat()); //无法访问
法2. 直接在外面定义
class Person{
constructor(name, age){
this.name = name;
this.age = age;
}
say(baz){
children.call(this, baz);
}
}
function children(baz){
return this.bar = baz;
}
static 静态属性和方法
静态方法是不会被实例继承的,而是通过类直接调用的
class Person{
static a(){
console.log(a);
};
}
console.log(Person.a);
静态属性
class Person{
static a = 1;
}
这样定义属性(static a = 1)也可以,但是有兼容性问题,是比较新的做法,一般不会这么做
比较多的做法是:
class Person{}
Person.a = 1;
取值函数和存值函数
对象中定义
var obj = {
get a(){
console.log(a);
},
set b(val){
console.log(2);
}
}
obj.a;
类当中也可
class Person{
get a(){
console.log(a);
}
set b(val){
console.log(2);
}
}
let person = new Person();
person.a;
person.b = 4; //2
get和set不要认为是一种方法,是一种取值和存值的操作,就当属性那样访问就好了
继承extends
ES6当中的继承非常容易,以前要来回倒腾原型链
super用法: 在constructor中,以函数的方式执行
class Parent{
constructor(name = 'zhangsan'){
this.name = name;
}
static a(){
console.log(1);
};
}
//派生类
class Child extends Parent{
constructor(name = 'lisi', age = '18'){
//this.age = age; 这里的this的指向是有问题的,super必须在构造器内部,使用this之前要先用super把父级的整个实例继承过来,才可以用this
super(name); //加工父级构造器,拿到基于父级实例,过了一遍之后返回实例
this.age = age;
this.type = 'child';
}
}
console.log(new Child());
console.log(new Child().a()); //报错
console.log(Parent.a); //1
console.log(new Child().age);
修饰器模式
定义:为对象添加新的功能,而不改变原有的结构和功能
语法:@ + 自定义关键字,修饰和它相邻的下一个方法
@testable
class Person{
constructor(name, age){
this.name = name;
this.age = age;
}
@readonly
say(){
console.log(1);
}
eat(){
console.log('I can eat');
}
}
function readonly(target, name, descriptor){
console.log(target, name, descriptor); // Person、属性名say、say属性描述符
descriptor.writable = false;
}
function testable(target){
console.log(target); // Person
}
let person = new Person();
person.say();
target就是当前要修饰的对象:整个Person
通过参数添加一系列功能,实现业务和逻辑相分离。
埋点分析:每做一个数据操作,就有数据处理对应的动作,类似控制台日志。
//埋点代码,记录相应函数执行所对应的结果
let log = (type) => {
return function(target, name, descriptor){
let src_method = descriptor.value; //descriptor.value就是对应的函数
descriptor.value = (...arg) => { //动态的值,不能用src_method替代
src_method.apply(target, arg);
console.log(type);
}
}
}
class AD{
//逻辑代码
@log('show')
show(){
console.log('ad is show');
}
@log('click')
click(){
console.log('ad is click');
}
}
let ad = new AD();
ad.show();
ad.click();
主体逻辑在一部分,埋点逻辑在另外一部分,复用性更强
设计模式总原则:开放封闭原则(多拓展开放,对修改封闭)