• 技术文章 >web前端 >js教程

    JavaScript ES6中CLASS的使用详解

    高洛峰高洛峰2016-12-06 09:30:56原创769
    前言

    对于javascript来说,类是一种可选(而不是必须)的设计模式,而且在JavaScript这样的[[Prototype]] 语言中实现类是很蹩脚的。

    这种蹩脚的感觉不只是来源于语法,虽然语法是很重要的原因。js里面有许多语法的缺点:繁琐杂乱的.prototype 引用、试图调用原型链上层同名函数时的显式伪多态以及不可靠、不美观而且容易被误解成“构造函数”的.constructor。

    除此之外,类设计其实还存在更进一步的问题。传统面向类的语言中父类和子类、子类和实例之间其实是复制操作,但是在[[Prototype]] 中并没有复制。

    对象关联代码和行为委托使用了[[Prototype]] 而不是将它藏起来,对比其简洁性可以看出,类并不适用于JavaScript。

    ES6中CLASS的使用

    javascript传统做法是当生成一个对象实例,需要定义构造函数,然后通过new的方式完成。

    function StdInfo(){
      this.name = "job";     
      this.age = 30;     
    }
     
    StdInfo.prototype.getNames = function (){
      console.log("name:"+this.name);       
    }
    //得到一个学员信息对象
    var p = new StdInfo()

    javacript中只有对象,没有类。它是是基于原型的语言,原型对象是新对象的模板,它将自身的属性共享给新对象。这样的写法和传统面向对象语言差异很大,很容易让新手感到困惑。

    定义类

    到了ES6添加了类,作为对象的模板。通过class来定义一个类:

    //定义类
    class StdInfo {
      constructor(){
        this.name = "job";     
        this.age = 30;  
      }
      //定义在类中的方法不需要添加function
      getNames(){
        console.log("name:"+this.name);  
      }
    }
    //使用new的方式得到一个实例对象
    var p = new StdInfo();

    上面的写法更加清晰、更像面向对象编程的语法,看起来也更容易理解。

    定义的类只是语法糖,目的是让我们用更简洁明了的语法创建对象及处理相关的继承。

    //定义类
    class StdInfo {
      //...
    }
    console.log(typeof StdInfo); //function
     
    console.log(StdInfo === StdInfo.prototype.constructor); //true

    从上面的测试中可以看出来,类的类型就是一个函数,是一个“特殊函数”,指向的是构造函数。

    函数的定义方式有函数声明和函数表达式两种,类的定义方式也有两种,分别是:类声明和类表达式。

    类声明

    类声明是定义类的一种方式,使用关键字class,后面跟上类名,然后就是一对大括号。把这一类需要定义的方法放在大括号中。

    //定义类,可以省略constructor
    class StdInfo {
      getNames(){
        console.log("name:"+this.name);
      }
    }
    // -------------------------------------
    //定义类,加上constructor
    class StdInfo {
      //使用new定义实例对象时,自动调用这个函数,传入参数
      constructor(name,age){
        this.name = name;     
        this.age = age;  
      }
       
      getNames(){
        console.log("name:"+this.name);  
      }
    }
    //定义实例对象时,传入参数
    var p = new StdInfo("job",30)

    constructor是一个默认方法,使用new来定义实例对象时,自动执行constructor函数,传入所需要的参数,执行完constructor后自动返回实例对象。

    一个类中只能有一个constructor函数,定义多个会报错。

    constructor中的this指向新创建的实例对象,利用this往新创建的实例对象扩展属性。

    在定义实例对象时,不需要在初始化阶段做一些事,可以不用显示的写constructor函数。如果没有显式定义,一个空的constructor方法会被默认添加,constructor(){}

    类表达式

    类表达式是定义类的另一种形式,类似于函数表达式,把一个函数作为值赋给变量。可以把定义的类赋值给一个变量,这时候变量就为类名。class关键字之后的类名可有可无,如果存在,则只能在类内部使用。

    定义类 class后面有类名:

    const People = class StdInfo {
      constructor(){
        console.log(StdInfo); //可以打印出值,是一个函数
      }
    }
     
    new People();
    new StdInfo(); //报错,StdInfo is not defined;

    定义类 class后面没有类名:

    const People = class {
      constructor(){
     
      }
    }
     
    new People();

    立即执行的类:

    const p = new class {
      constructor(name,age){
        console.log(name,age);
      }
    }("job",30)

    立即执行的类,在类前要加上new。p为类的实例对象。

    不存在变量提升

    定义类不存在变量提升,只能先定义类后使用,跟函数声明有区别的。

    //-----函数声明-------
    //定义前可以先使用,因为函数声明提升的缘故,调用合法。
    func();
    function func(){}
     
    //-----定义类---------------
    new StdInfo(); //报错,StdInfo is not defined
    class StdInfo{}

    EXTENDS继承

    使用extends关键字实现类之间的继承。这比在ES5中使用继承要方便很多。

    //定义类父类
    class Parent {
      constructor(name,age){
        this.name = name;
        this.age = age;
      }
     
      speakSometing(){
        console.log("I can speek chinese");
      }
    }
    //定义子类,继承父类
    class Child extends Parent {
      coding(){
        console.log("coding javascript");
      }
    }
     
    var c = new Child();
     
    //可以调用父类的方法
    c.speakSometing(); // I can speek chinese

    使用继承的方式,子类就拥有了父类的方法。

    如果子类中有constructor构造函数,则必须使用调用super。

    //定义类父类
    class Parent {
      constructor(name,age){
        this.name = name;
        this.age = age;
      }
     
      speakSometing(){
        console.log("I can speek chinese");
      }
    }
    //定义子类,继承父类
    class Child extends Parent {
      constructor(name,age){
        //不调super(),则会报错 this is not defined
     
        //必须调用super
        super(name,age);
      }
     
      coding(){
        console.log("coding javascript");
      }
    }
     
    var c = new Child("job",30);
     
    //可以调用父类的方法
    c.speakSometing(); // I can speek chinese

    子类必须在constructor方法中调用super方法,否则新建实例时会报错(this is not defined)。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐: JavaScript
    上一篇:javascript入门之window对象 下一篇:JS 实时的时间
    Web大前端开发直播班

    相关文章推荐

    • node爬取数据实例:聊聊怎么抓取小说章节• 值得了解的几个实用JavaScript优化小技巧• 一起聊聊JavaScript函数式编程• JavaScript学习理解之JSON(总结分享)• 你能搞懂JS的this指向问题吗?看看这篇文章

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网