• js_类(class)


    创建类

    通过class关键字进行创建

    类的数据类型就是函数,类本身指向构造函数

            class Bar {
                doStuff() {
                    console.log('stuff');
                }
            }
    
            var b = new Bar();
            b.doStuff(); //stuff
            console.log(typeof Bar); //function
            console.log(Bar === Bar.prototype.constructor); //true
    
            function Bar() {
    
            }
            Bar.prototype = {
                constructor: Bar,
                doStuff() {
                    console.log('stuff');
                }
            }
            var b = new Bar();
            b.doStuff(); //stuff
    

    由上面的代码可以看出,类的数据类型就是函数,类本身就是构造函数,class更具体来说就是es6的语法糖,起到与构造函数相同的作用。

    类的所有方法都定义在类的prototype属性上,在类的实例上调用方法实际上是调用原型对象上的方法

            class Point {
                constructor() {
                    // ...
                }
    
                toString() {
                    // ...
                }
    
                toValue() {
                    // ...
                }
            }
    
            // 等同于
    
            Point.prototype = {
                constructor() {},
                toString() {},
                toValue() {},
            };
    
            class B {
                toValue() {}
            }
            let b = new B();
    
            console.log(b.toValue === B.prototype.toValue); //true
    

    通过object.assign向类添加方法

            class Point {
                constructor() {}
            }
    
            Object.assign(Point.pototype, {
                toString() {},
                toValue() {}
            })
    

    类内部的所有定义方法都是不可枚举的

            class Point {
                constructor() {}
                toString() {}
            }
    
            console.log(Object.keys(Point.prototype)); //[]
            console.log(Object.getOwnPropertyNames(Point.prototype)); //["constructor","toString"]
    

    constructor方法

    通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。

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

    写在constructor函数中的代码相当于写在构造函数本身中,即Point.prototype.constructor

    没有写在constructor函数中的代码,相当于写在原型对象中,即Point.prototype

    类的实例

    类只能通过new来进行调用,且所有的类的实例共享一个原型对象

            class Foo {
                constructor() {}
            }
            var foo1 = new Foo();
            var foo2 = new Foo();
            console.log(foo1.__proto__ == foo2.__proto__); //true
            //允许通过实例的__proto__属性对原型对象进行CRUD操作,其一经修改,所有的实例都会受到影响
    

    取值函数(getter)与存值函数(setter)

            class myClass {
                constructor() {}
                get prop() {
                    return 'getter';
                }
                set prop(val) {
                    console.log('setter: ' + val);
                }
            }
    
            let inst = new myClass();
            inst.prop = 123;
            console.log(inst.prop);
    

    上面代码中,prop属性有对应的存值函数和取值函数,因此赋值和读取行为都被自定义了。
    在ES5中有Object.getOwnPropertyDescriptor方法,用于获取指定对象的访问器属性或数据属性。

            var descriptor = Object.getOwnPropertyDescriptor(myClass.prototype, 'prop');
            console.log("get" in descriptor); //true
            console.log("set" in descriptor); //true
    

    属性表达式

    类的属性名,可以采用表达式

            let methodName = 'getArea';
            class Foo {
                constructor() {}
                    [methodName]() {
                        console.log('xxx');
                    }
            }
    
            var foo = new Foo();
            foo.getArea(); //'xxx'
    

    Class表达式

            const myClass = class Me {
                getClassName() {
                    return Me.name;
                }
            };
    
            let inst = new myClass();
            console.log(inst.getClassName()); //Me
            //在class外部,这个类只能使用myClass引用
            //Me只在class内部有定义
    

    通过class表达式立即执行class

            let person = new class {
                constructor(name) {
                    this.name = name;
                }
    
                sayName() {
                    console.log(this.name);
                }
            }('张三');
    
            person.sayName(); //张三
    
    • 严格模式

    类和模块内部默认严格模式,所以不需要使用'use strict'指定运行模式

    • 不存在提升

    类不存在变量提升,即 class Foo{} 与 new Foo() 的顺序不能搞混

    • name属性

    ES6的类本身只是ES5的构造函数的包装,因此可以通过 Foo.name 得到 class Foo{} 的name属性(即Foo)

    • Generator方法

    如果某个方法之前加上星号(*),就表示该方法是一个 Generator 函数。

    • this指向

    类的方法内部如果含有this,它默认指向类的实例。

    静态方法

    静态方法不会被实例继承

    类相当于实例的原型对象,所有在类中定义的方法都会被实例继承,但是在一个方法前加上static关键字,就表示该方法不会被实例继承,而是通过类来进行调用,这种方法被称为“静态方法”.

            class Foo {
                static classMethod() {
                    return 'hello';
                }
            }
            console.log(Foo.classMethod()); //hello
            var foo = new Foo();
            console.log(foo.classMethod()); //foo.classMethod is not a function
    

    静态方法的this指向类

    如果静态方法包含this关键字,此时this指向的是类。(静态方法可以和非静态方法重名)

            class Foo {
                static bar() {
                    this.baz();
                }
                baz() {
                    console.log('world');
                }
                static baz() {
                    console.log('hello');
                }
            }
            Foo.bar(); //hello
    

    父类的静态方法可以被子类继承,但需要通过子类的类来进行调用

            class Foo {
                static classMethod() {
                    return 'hello';
                }
            }
            class Bar extends Foo {
    
            }
            console.log(Bar.classMethod());
    

    静态方法也可以从super对象上调用。

            class Foo {
                static classMethod() {
                    return 'hello'
                }
            }
    
            class Bar extends Foo {
                static classMethod() {
                    return super.classMethod() + ', too';
                }
            }
            console.log(Bar.classMethod());
    

    实例属性的新写法

    实例属性可以定义在constructor()方法里面的this上面,也可以定义在类的最顶层。

            class IncreasingCounter {
                constructor() {
                    this._count = 0;// 定义在这儿相当于定义在构造函数内
                }
                get value() {
                    console.log('Getting the current value');
                    return this._count;
                }
                increment() {
                    this._count++;// 相当于定义在原型对象中
                }
            }
            var inc1 = new IncreasingCounter();
            var inc2 = new IncreasingCounter();
            inc1.increment();
            console.log(inc1.value); //Getting the current value 1
            console.log(inc2.value); //Getting the current value 0
    
            class IncreasingCounter {
                _count = 0;// 相当于定义在原型对象
                get value() {
                    console.log('Getting the current value');
                    return this._count;
                }
                increment() {
                    this._count++;
                }
            }
            var inc1 = new IncreasingCounter();
            var inc2 = new IncreasingCounter();
            inc1.increment();
            console.log(inc1.value);
            console.log(inc2.value);
    

    写在类的顶端的属性和写在constructor方法中的属性是有区别的。写在类的顶端的属性相当于写在类的原型对象内,而写在constructor方法中的属性则是写在构造函数中的。

    静态属性

    class MyClass {
        static myStaticProp = 45;
        constructor() {
            this.getVal = function () {
                console.log(MyClass.myStaticProp);
            }
        }
    }
    var c = new MyClass();
    c.getVal(); //45
    

    类的静态属性只属于类,与实例无关

  • 相关阅读:
    INSERT
    jQuery选择器
    工厂模式
    快乐的Linux命令行
    Linux常用命令与基本概念
    RAC 集群更换IP
    RMAN-03009 ORA-19504 ORA-27038
    Redhat 6.4_联网 yum 配置
    /dev/sda3: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY
    nginx安装笔记
  • 原文地址:https://www.cnblogs.com/Syinho/p/13369556.html
Copyright © 2020-2023  润新知