首页 > 其他 > 详细

05、ES6 class

时间:2020-05-06 17:12:19      阅读:50      评论:0      收藏:0      [点我收藏+]

类与对象

OOP-面向对象开发(核心是封装)

es5函数封装

//面向过程的封装: 封装一个自执行的匿名函数,这样内部的各种属性和方法就不会暴露在全局下面。面向过程可以暂时理解为函数

es6的类封装

//类相当于一个工厂,只要给适当的参数就会生产出对应的对象。
//构造函数相当于接头人,负责接收参数,有固定名字: constructor
//实例化相当于生产的过程,就是类创建对象的过程

class car {
    //constructor构造函数用来接收参数
    constructor([name,color]){ //这里函数的写法,跟对象里的简洁表示法一样
        this.name = name; //this是在一个类中能被访问的一个关键字
        this.color = color; //若没有this,下面实例化完的对象就访问不到这里的属性
        this.number = 0;
        console.log(‘开始接收参数‘);
        console.log(name,color);
    }

    add(){
        this.number += 1;    //这里可以对constructor里面的参数进行更改
        console.log(this.number);
    }
}

//只要class准备好了就可以实例化了
const che =  new car([‘奔驰‘,‘红色‘]); //这里相当于调用constructor,括号里面可以传递参数

console.log(che); //上面有了this的关键字,这里就能访问到属性了

//实例化之后就可以调用里面的方法了
che.add();

 

class的三大特性

一、封装

二、继承

三、多态: 同一个接口不同的表现

 

静态属性与静态方法

1、不会被类实例所拥有的属性与方法,只是自身拥有。

2、只能通过类调用。

 

静态属性的定义与调用

定义

第一种,在类里面,在constructor前面

//定义静态属性一: 在类里面
//static 属性名 = 属性值
static stt = ‘constructor前面定义的静态属性‘;

//修改静态属性

 constructor(){
   //对第一种方式的,静态属性进行修改。
   //必须先实例化再调用才生效
   haha.stt = ‘01234‘;
 }

 

第二种,在类外面

// 定义静态属性二: 在类外面
// 定义静态属性: 类名 . 属性名 = 属性值 
haha.str = ‘静态属性‘; 

 

调用

console.log(haha.stt); //调用静态属性,类名 . 静态属性名。
console.log(haha.str); //调用静态属性,类名 . 静态属性名。

 

静态方法的定义与调用

定义

//定义普通方法
bb(){
    console.log(‘静态方法跟普通方法重名是没关系的,互不影响‘);
}

//定义静态方法
static bb(name){
    console.log(‘我是静态方法,只有class才能调用。传进来的参数是:‘ + name);
}

 

调用

//调用静态方法,只有该class才能调用静态方法
haha.bb(‘大比‘);  //类名 . 静态方法名

 

类表达式

//类表达式
const p = class a{  //若不需要,a可以省略
    constructor(){
        console.log(‘这里p是 === a的,a仅限于内部使用‘);
    }
}
// new p();


//类的声明
class bb{
    constructor(){
        console.log(‘类的声明‘);
    }
}
// new bb();


//类的自执行
const aa = new class p{
    constructor(){
        p.a = 26;
        console.log(p.a);
    }
    
}()

 

getter、setter

//类似给属性提供钩子。在获取属性和设置属性的时候做一些额外的事情

 

ES5的getter、setter

1、在字面量中书写get、set方法

const obj = {
    _name:‘123‘,
    get name(){     //获取name属性
        console.log(‘这是获取name的操作‘); //除了返回name之外,还可以做其他额外的操作
        return this._name;
    },
    set name(val){  //设置name属性
        this._name = val;
    }
}
//设置name,实际上是设置_name
obj.name = ‘设置name,会自动调用set name方法‘;

//获取name,实际上是访问_name
console.log(obj.name);

//name属性名 跟 get、set方法名不可以重名。 若重名会报错,栈内存溢出
//先触发get name,里面this.name访问了name,访问了name又会触发get name ......

 

2、Object.defineProperty

const obj = {
    _age : 2
}

//设置/添加属性
Object.defineProperty(obj,‘age‘,{  //这里同样不能重名
    //value : 88,
    get : function(){
        console.log(‘正在使用get方法‘);
        return this._age; //这里同样不能重名
    },
    set : function(val){
        console.log(‘正在使用set方法‘);
        this._age = val; //这里同样不能重名
    }
});
//第一个参数: obj是表示要操作的对象
//第二个参数: ‘age‘表示需要设置/添加的属性
//第三个参数: 一个对象,里面是对属性的描述
//value是属性的值,即第二个参数的值。
//是否可以枚举: enumerable:true 。默认是false,不可以被遍历出来
//描述还可以添加是否可读。

// console.log(obj); //里面多出了一个age属性。不过默认age属性是不可以被遍历出来的

//修改age
obj.age = 88;

//获取age
console.log(obj.age);

 

ES6的class中,getter、setter

class obj{
    constructor(){
        this._address = ‘北京‘;
    }
    get address(){
        console.log(‘class里面的get操作‘);
        return `我家住在${this._address}`;
    }
    set address(val){
        console.log(‘class里面的set操作‘);
        this._address = val;
    }
}

//首先需要实例化
const p = new obj();

//修改address
p.address = ‘上海‘;

//获取address
console.log(p.address);

 

name属性 与 new.target属性

name属性

//name属性获取class类名
class bb {}
console.log(bb.name); //类名是bb

const aa = class {}
console.log(aa.name); //类名是aa

const cc = class dd{}
console.log(cc.name); //类名是dd

 

new.target属性

//表示该类/函数自身。只有在类 或 构造函数/函数 里面才可以访问

ass Car{ //类使用
    constructor(){
        console.log(new.target); //打印出这个类本身
    }
}
new Car(); //new后面的Car(),就是new.target属性


function ccr(){ //构造函数 或 普通函数都可以使用
    //判断是否使用new关键字调用
    if(ccr == new.target){ //还可以这样判断(this instanceof ccr),详情看下面构造函数流程
        console.log(new.target); //只有构造函数调用,才能正常使用new.target
    }else{
        throw Error(‘必须用new关键字调用‘);
    }
}
new ccr();
//构造函数调用 跟 普通函数调用 走的流程不一样
//1、构造函数this会先指向一个新的空对象
//2、构造函数的prototype属性会成为 空对象的原型
//3、this赋值给这个空对象
//4、执行函数
//5、若该函数没有返回值的话,则返回this。即之前那个空对象

 

 

ES5模拟类

1、构造函数this会先指向一个新的空对象

2、构造函数的prototype属性会成为 空对象的原型

3、this赋值给这个空对象

4、执行函数

5、若该函数没有返回值的话,则返回this。即之前那个空对象

//将构造函数的流程封装成一个函数
function Constructor(fn,args){
    // 1、构造函数this会先指向一个新的空对象
    // 2、构造函数的prototype属性会成为 空对象的原型
    var _this = Object.create(fn.prototype);
    // var _this = Object.create(fn.prototype);

    // 3、this赋值给这个空对象
    var res = fn.apply(_this,args);
    // var res = fn.apply(_this, args);

    // 4、执行函数 
    // 5、若该函数没有返回值的话,则返回this。即之前那个空对象
    return res ? res : _this;
    // return res ? res : _this;
}

//构建一个普通函数
function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype.say = function() {
    console.log(`我叫${this.name},我今年${this.age}岁了`);
}

//将 普通函数 转为 构造函数
var ren = Constructor(Person,[‘张三‘,88]);
console.log(ren);

 

类的继承

class fu{    //定义父类
    constructor(name,sex,age){
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
    shuo(){     //定义父类的方法
        console.log(`我的名字是${this.name},性别是${this.sex},年龄是${this.age}`);
    }
}

class zi extends fu{    //定义子类,并继承父类
    constructor(name,sex,age,skill){    //接收父类的参数 和 子类的参数
        super(name,sex,age);    //给父类传入参数
        this.skill = skill;
    }
    jineng(){  //定义子类的方法
        console.log(`我的技能有${this.skill}`);
    }
}

const person = new zi(‘小蝴蝶‘,‘女‘,3,‘嚎啕大哭‘); //实例化子类,并传入参数

person.shuo();    //调用父类的方法

person.jineng();    //调用子类方法

 

 

super关键字的其他内容

作为父类构造函数调用

//在继承中有使用到,在调用之后子类就会有父类的属性和方法。
//(相当于把子类的this放到父类的构造函数中运行一遍,后继续走子类的构造函数)
class fu{
    constructor(name){
        this.name = name;
    }
}
class zi extends fu{
    constructor(name,sex){
        super(name);
        this.sex = sex;
    }
    methods(){
        console.log(`我的名字是${this.name},我是${this.sex}生。`);
    }
}
const child = new zi(‘大白‘,‘女‘);
child.methods();

 

作为对象的方式调用。

//在调用super,父类的this始终是子类的this

//在非静态方法中访问super,访问的是父类原型
class fu{
    fusay(){
        console.log(‘您好!‘);
    }
}

class zi extends fu{
    zisay(){
        console.log(super.fusay); //这样的话调用子类的zisay就会输出父类的fusay函数本身。
        //若要执行父类的fusay,这里也可以直接调用,如: super.fusay()
    }
}
const child = new zi();
child.zisay(); //作为对象调用的时候,不使用super也可以调用父类的方法

 

//在静态方法中访问super,访问的是父类
class fu{
}
fu.total = 898;

class zi extends fu{
    static tot(){
        console.log(super.total);
    }
}
zi.tot();

 

//验证: 调用super时,父类的this始终是子类的this
class fu{
    check(_this){
        console.log(_this === this); //接收子类的this,并把子类的this与父类的this相比较
    }
}
class zi extends fu{
    use(){
        super.check(this); //调用父类check方法,并把子类的this传过去
    }
}
const yan = new zi();
yan.use();    //true

 

简单的多态

//同一个接口在不同的情况下,做不同的事情。即相同的接口,不同的表现

//好处: 提高类的扩充性和灵活性。还可以暴露接口,让子类完成父类不需要完成的内容。

class human{
    say(){
        console.log(‘我是人‘);
    }
}
class man extends human{  //多态必须要通过继承来实现。子类写一个父类同名的方法即可达到覆盖的效果
    say(){
        console.log(‘我是男人‘);
    }
}
class woman extends human{
    say(){
        console.log(‘我是女人‘);
        super.say();  //同样还可以调用父类的say方法
    }
}

new man().say();
new woman().say();

 

 

重载

//根据函数的参数类型、参数个数,让函数做不一样的事情

class simpleCalc{
    addCale(...args){
        if(args.length < 2){
            return this.donot();
        }else{
            return this.add(args);
        }
    }
    donot(){
        console.log(‘参数不够,不执行‘);
    }
    add(args){
        console.log(args.reduce(function(a,b){return a+b}));
    }
}
new simpleCalc().addCale(1);

 

 

ES5中的继承

function P(){  //父函数
    this.name = ‘萌萌‘;
    this.sex = ‘女‘;
    this.say = function(){
        console.log(‘哈哈哈‘);
    }
}
P.prototype.test = function(){  //原型的属性和方法不可通过call继承
    console.log(‘我是P的原型方法‘);
}

function C(){  //子函数
    P.call(this);  //这样就执行了P,并把当前this传过去。这样就继承了父函数的属性和方法,但不包括原型的属性和方法。
    this.age = 18;
    this.address = ‘北京‘;
}

//若需要继承父函数的原型属性和方法,需要
C.prototype = new P(); //C的prototype 可以访问到 P的prototype
//P的实例也就是P函数的prototype属性,所以P的实例可以访问到P.prototype的方法

var bb = new C();  //实例化子函数
bb.say();  //成功执行父函数的方法
console.log(bb.address); //成功执行子函数的属性
bb.test();  //成功执行父函数的原型方法

 

05、ES6 class

原文:https://www.cnblogs.com/mingliangge/p/12620154.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!