zoukankan      html  css  js  c++  java
  • 【es6】class

    class是es6引入的最重要特性之一。在没有class之前,我们只能通过原型链来模拟类。

    基本用法

    如果你用过java这样的纯面向对象语言,那么你会对class的语法非常熟悉。

    class People {
        constructor(name) { //构造函数
              this.name = name;
        }
        sayName() {
              console.log(this.name);
        }
    }

    上面定义了一个People类,他有一个属性 name 和一个方法 sayName(),还有一个构造函数; 
    你可以这样使用这个类:

    var p = new People("Tom");
    p.sayName();

    就像函数有函数声明和函数表达式两种定义方式,类也可以通过类表达式来定义:

    let People = class {
        constructor(name) { //构造函数
              this.name = name;
        }
        sayName() {
              console.log(this.name);
        }
      }

    你可能以为类声明和类表达式的区别在于变量提升的不同。但是事实是无论是类声明还是类表达式的方式来定义,都不会有变量提升。所以下面的写法是错的:

    var p = new People("Tom");    //错误,People 未定义
    class People {
        //...
    };

    类中的所有方法默认都是 strict mode,所以不用再次声明了。

    继承

    通过关键字 extends 来继承一个类,并且,可以通过 super 关键字来引用父类。

    class People {
        constructor(name) { //构造函数
              this.name = name;
        }
        sayName() {
              console.log(this.name);
        }
    }
    
    class Student extends People {
        constructor(name, grade) { //构造函数
            super(name);    //调用父类构造函数
              this.grade = grade;
        }
        sayGrade() {
              console.log(this.grade);
        }
    }

    上面的例子中我们定义了一个 Student ,他是 People 的子类。

    注意我们在 constructor 中是如何通过 super 调用父类的构造函数的。

    getters & setters

    现在我们可以通过 get 和 set 关键字来定义 getters 和 setters 了。

    下面我们给 name 属性定义 getter 和 setter

    class People {
        constructor(name) { //构造函数
              this.name = name;
        }
        get name() {
            return this._name.toUpperCase();
        }
        set name(name) {
            this._name = name;
        }
        sayName() {
              console.log(this.name);
        }
    }
    var p = new People("tom");
    console.log(p.name);    //TOM
    console.log(p._name);    //tom
    p.sayName();    //TOM

    仔细看上面的例子,搞清楚最后三行分别会输出什么,就明白getter 和 setter该怎么用了。

    主要是要区分 this._name 和 this.name 的区别。因为我们定义了 name 的读写器,而没有定义 _name 的读写器,所以访问这两个属性的结果是不同的。

    但是要注意一点,不要这样写:

    set name(name) {
        this.name = name;
    }

    因为给 this.name 赋值的时候会调用 set name ,这样会导致无限递归直到栈溢出。

    静态方法

    通过 static 关键字定义静态方法:

    class People {
        constructor(name) { //构造函数
              this.name = name;
        }
        sayName() {
              console.log(this.name);
        }
        static formatName(name) {
            return name[0].toUpperCase() + name.sustr(1).toLowerCase();
        }
    }
    
    console.log(People.formatName("tom"));

    静态方法一般用来提供一些工具方法。

    私有属性

    很不幸的时ES6并没有提供对私有属性的语法支持,但是我们可以通过闭包来实现私有属性。

    var People = (function() {
      var p = new WeakMap();
      class People {
        constructor(name) { //构造函数
              var privateProperties = {
            name: name
        };
        p.set(this, privateProperties);
        }
        sayName() {
              console.log(this.name);
        }
    
        get name() {
          return p.get(this).name;
        }
    }
    return People;
    })();
    
    var p = new People("tom");
    console.log(p.name);
    p.sayName();
    
    var p2 = new People("bob");
    console.log(p2.name);
    p2.sayName();
  • 相关阅读:
    整数因子分解问题(递归分治法、动态规划)
    背包问题(动态规划 C/C++)
    划分问题(Java 动态规划)
    算法:Common Subsequence(动态规划 Java 最长子序列)
    算法:矩阵连乘(Java)动态规划
    Frogs‘ Neighborhood(POJ 1659 C/C++)
    算法:线性时间选择(C/C++)
    sort(hdu oj 1425)计数排序和快速排序
    快速排序(递归和分治)
    a^b(取模运算)
  • 原文地址:https://www.cnblogs.com/shytong/p/5199345.html
Copyright © 2011-2022 走看看