es6--Class:概述、属性和方法、继承

一、初识Class

1.1 Class是什么

传统面向对象的编程序语言都是【类】的概念,对象都是由类创建出来,而早期 JavaScript 中是没有类的,面向对象大多都是基于构造函数和原型实现的,但是 ECMAScript 6 规范开始增加了【类】相关的语法,使得 JavaScript 中的面向对象实现方式更加标准  

a.认识Class

 类可以看做是对象的模板,用一个类可以创建出许多不同的对象


1.2  Class的基本用法

类名一般首字母大写

语法:class 类名 {}

 // 创建类

class Person{

        // 此处编写封装逻辑

}

      class Person {}

      // 实例化类
      let re = new Person();
      console.log(re);

      let o = new Person();
      console.log(o);

      class Dog {}

      let d = new Dog();

示例:

<script>
     class Person {

            // 实例化时执行构造方法,所以必须有构造方法即constructor,但是可以不写出来
            // 如果我们不写 constructor ,那么会自动的帮我们创建这个构造方法
            constructor(name, age) {
                // console.log('实例化时执行构造方法');
                //this 代表实例对象,上面定义的是实例属性/方法
                this.name = name;
                this.age = age;

                // 一般在构造方法中定义属性,方法不在构造方法中定义
                // this.speak = () => {};
            }


            // 各实例共享的方法
            speak() {
                console.log('speak');
            }

        }


        const zs = new Person('ZS', 18);
        const ls = new Person('LS', 28);

        console.log(zs.name);
        console.log(zs.age);
        console.log(zs.speak);

        zs.speak();

        console.log(ls.name);
        console.log(ls.age);
        console.log(ls.speak);

        console.log(zs.speak === ls.speak);
</script>

总结:

  • 关键字 class 封装了所有的实例属性和方法

  • 类中封装的并不是变量和函数,因此不能使用关键字 letconstvar


1.3 constructor()

constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法

一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加

class Point {
}

// 等同于
class Point {
  constructor() {}
}

constructor方法默认返回实例对象(即this),完全可以指定返回另外一个对象

类必须使用new调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用new也可以执行

<script>
  class Person {
    // 实例化时 立即执行
    // 构造函数、构造方法、构造器
    constructor (name, age) {
      this.name = name;
      this.age = age;
    }
	// 实例方法
    walk () {
      console.log(this.name + '正在走路...');
    }
  }
	
  // 实例化
  let p1 = new Person('小明', 18);
  p1.walk();
</script>

总结:

  • constructor 是类中固定的方法名

  • constructor 方法在实例化时立即执行

  • constructor 方法接收实例化时传入的参数

  • constructor 并非是类中必须要存在的方法

 


1.4 Class与构造函数

类:

         //类
        class Person {

            constructor(name, age) {
                this.name = name;
                this.age = age;

                // this.speak = () => {};
            }

            speak() {
                console.log('speak');
            }

            run() {}
        }

        //类也可以在其圆形上声明方法(不推荐这种写法)
        Person.prototype.run = function() {};

        console.log(typeof Person);

        console.log(Person.prototype.speak); //类也可以在其圆形上找到该方法

构造函数:

<script>
        //构造函数
        function Person(name, age) {
            this.name = name;
            this.age = age;
        }

        //构造函数的方法一般写在其原型上
        Person.prototype.speak = function() {};
</script>


1.5 Class的两种定义形式

a.声明形式

 class Person {

            constructor() {}

            speak() {}

        }

b.表达式形式

const Person = class {

            constructor() {

                console.log('constructor');

            }

            speak() {}

        };

        new Person();

c.立即执行的匿名类

new(class {

            constructor() {

                console.log('constructor');

            }

        })();


1.6 取值函数(getter)和存值函数(setter)

与 ES5 一样,在“类”的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为

class MyClass {
            constructor() {
                // ...
            }
            get prop() {
                return 'getter';
            }
            set prop(value) {
                console.log('setter: ' + value);
            }
        }

        let inst = new MyClass();

        inst.prop = 123;
        // setter: 123

        inst.prop
            // 'gette


 二、Class的属性和方法

2.1 实例属性和实例方法、静态属性和静态方法

a.实例属性

方法就是值为函数的特殊属性

 class Person {

            //设置默认属性
            age = 14;
            name = 'zhangsan';
            sex = 'male';

            //实例方法
            getSex = function() {
                return this.sex;
            };

            //在这里可以对默认属性进行修改
            constructor(name, sex) {
                this.name = name;
                this.age = 18;
                this.sex = sex;
            }

            // speak() {
            //     this.age = 18;
            // }
        }

        const p = new Person('Alex');
        console.log(p.name);
        console.log(p.age);

b.静态方法和静态属性

类相当于实例的原型,所有在类中定义的方法,都会被实例继承

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

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

<script>
  class Person {

            // 实例属性
            constructor(name) {
                this.name = name;
            }

            //  不要这么写,目前只是提案,有兼容性问题
            // static version = '1.0';

            //静态方法 写法1 --推荐
            static getVersion() {
                //推荐将静态属性写成这种“静态方法”的形式
                return '1.0';
            }


            //实例方法--实例对象的方法
            speak() {
                console.log('speak');

                // 实例对象中的this指向实例对象
                console.log(this);
            }


        }

        //静态方法 写法2--不推荐
        // Person.getVersion = function() {
        //     return '1.0';
        // }


        //1
        // Person.version = '1.0'; //静态属性写法,但是不推荐,没得必要写在类的外面
        // console.log(Person.version);


        //2 静态属性,必须使用new进行实例化后再调用
        const p = new Person('Alex');
        p.speak(); //调用实例对象的方法
        console.log(p.name); //Alex


        //3.静态方法可以不使用new 进行实例化即可调用
        console.log(Person.getVersion()); //1.0
</script>

 

总结:

  • static 关键字用于声明静态属性和方法

  • 静态属性和方法直接通过类名进行访问

 


2.2 私有属性和方法

a.为什么需要私有属性和方法

私有方法和私有属性,是只能在类的内部访问的方法和属性,外部不能访问

 一般情况下,类的属性和方法都是公开的

公有的属性和方法可以被外界修改,造成意想不到的错误

示例:

 class Person {
            //实例属性
            constructor(name) {
                this.name = name;
            }

            //实例方法
            speak() {
                console.log('speak');
            }

            // 实例方法
            getName() {
                return this.name;
            }
        }

        //实例化属性
        const p = new Person('Alex');

        console.log(p.name);

        p.speak();

        // ....
        p.name = 'zs';
        console.log(p.name);

b.模拟私有属性和方法

1._ 开头表示私有(不具备很强的约束力)

 class Person {
            constructor(name) {
                this._name = name;
            }

            speak() {
                console.log('speak');
            }

            getName() {
                return this._name;
            }
        }

        const p = new Person('Alex');
        console.log(p.name);

        p.name = 'zd';
        console.log(p.getName());

2.将私有属性和方法移出类(具有很强的约束力)

<script>
        (function() {

            let name = '';

            class Person {
                constructor(username) {
                    // this.name = name;
                    name = username;
                }

                speak() {
                    console.log('speak');
                }

                getName() {
                    return name;
                }
            }

            window.Person = Person;
        })();

        (function() {
            const p = new Person('Alex');

            console.log(p.name);

            console.log(p.getName());
        })();
    </script>


三、Class的继承

一种简单的继承:

 //一种简单的继承,通过拷贝其原型来实现
        var lynkCoProtype = {
            model: "领克",
            getModel: function() {
                console.log("车辆模具是:" + this.model);
            }
        };

        var volvo = Object.create(lynkCoProtype, {
            model: {
                value: "沃尔沃"
            }
        });

        volvo.getModel();

3.1 extends

子类继承父类

<script>
     class Person {

            constructor(name, sex) {
                this.name = name;
                this.sex = sex;

                this.say = function() {
                    console.log('say');
                };
            }

            speak() {
                console.log('speak');
            }

            static speak() {
                console.log('static speak');
            }
        }

        Person.version = '1.0';

        class Programmer extends Person {
            constructor(name, sex) { 
                super(name, sex); //子类中调用父类的构造方法利用super();调用父类的constructor()
            }
        }

        const zs = new Programmer('zs', '男');

        console.log(zs.name);
        console.log(zs.sex);

        zs.say();
        zs.speak();

        Programmer.speak();

        console.log(Programmer.version);
</script>

注意:

子类必须在constructor方法中调用super方法,否则新建实例时会报错

这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法

如果不调用super方法,子类就得不到this对象

在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错--这是因为子类实例的构建,基于父类实例,只有super方法才能调用父类实例


 改写继承的属性或方法

 <script>
        class Person {

            constructor(name, sex) {
                this.name = name;
                this.sex = sex;

                this.say = function() {
                    console.log('say');
                };
            }

            speak() {
                console.log('speak');
            }

            static speak() {
                console.log('static speak');
            }
        }

        Person.version = '1.0';

        // 子类
        class Programmer extends Person {

            constructor(name, sex, feature) {
                // this.feature = feature; ×

                // this 操作不能放在 super 前面
                super(name, sex);

                this.feature = feature;
            }

            hi() {
                console.log('hi');
            }

            // 同名覆盖
            speak() {
                console.log('Programmer speak');
            }

            static speak() {
                console.log('Programmer static speak');
            }
        }
        Programmer.version = '2.0';

        const zs = new Programmer('zs', '男', '秃头');

        console.log(zs.name);
        console.log(zs.sex);
        console.log(zs.feature);

        zs.say();
        zs.speak();
        zs.hi();
        Programmer.speak();

        console.log(Programmer.version);
</script>


3.2 super

super这个关键字,既可以当作函数使用,也可以当作对象使用,就是用来调用父类的方法或属性

在继承的过程中子类中 constructor 中必须调 super 函数,否则会有语法错误

a.作为函数调用

代表父类的构造方法,只能用在子类的构造方法中,用在其他地方就会报错

super 虽然代表了父类的构造方法,但是内部的 this 指向子类的实例

<script>
      class Person {
            constructor(name) {
                this.name = name;

                console.log(this);
            }
        }

        class Programmer extends Person {
            constructor(name, sex) {
                super(name, sex);
            }

            // hi() {
            //   super(); // ×
            // }
        }

        // new Person();
        new Programmer();
</script>


b.作为对象使用

b.1.在构造方法中使用或一般方法中使用:

super 代表父类的原型对象 Person.prototype

所以定义在父类实例上的方法或属性,是无法通过 super 调用的

通过 super 调用父类的方法时,方法内部的 this 指向当前的子类实例

 class Person {
            constructor(name) {
                this.name = name;

                console.log(this);
            }

            speak() {
                console.log('speak');
                // console.log(this);
            }

            static speak() {
                console.log('Person speak');
                console.log(this);
            }
        }

        class Programmer extends Person {
            constructor(name, sex) {
                super(name, sex);

                // console.log(super.name);
                // super.speak();
            }

            // hi() {
            //   super(); // ×
            // }

            speak() {
                super.speak();
                console.log('Programmer speak');
            }
        }
        new Programmer();

b.2.在静态方法中使用:

指向父类,而不是父类的原型对象

通过 super 调用父类的方法时,方法内部的 this 指向当前的子类,而不是子类的实例

 class Person {
            constructor(name) {
                this.name = name;

                console.log(this);
            }

            speak() {
                console.log('speak');
                // console.log(this);
            }

            static speak() {
                console.log('Person speak');
                console.log(this);
            }
        }

        class Programmer extends Person {
            constructor(name, sex) {
                super(name, sex);

                // console.log(super.name);
                // super.speak();
            }

            // hi() {
            //   super(); // ×
            // }

            speak() {
                super.speak();
                console.log('Programmer speak');
            }


            static speak() {
                super.speak();
                console.log('Programmer speak');
            }
        }
        // new Person();
        // new Programmer();
        Programmer.speak();

c.注意事项

使用 super 的时候,必须显式指定是作为函数还是作为对象使用,否则会报错

 <script>
        class Person {
            constructor(name) {
                this.name = name;
            }

            speak() {
                console.log('speak');
            }
        }

        class Programmer extends Person {
            constructor(name, sex) {
                super(name, sex);

                // console.log(super);
                console.log(super()); //作为函数
                // console.log(super.speak); //作为对象
            }
        }
</script>

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白小白从不日白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值