美文网首页程序员让前端飞
es6之class 基本用法解析

es6之class 基本用法解析

作者: 88b61f4ab233 | 来源:发表于2018-12-06 17:59 被阅读6次

    javaScript 语言中,生成实例对象的传统方法是通过构造函数,与传统的面向对象语言(比如 C++ 和 Java)差异很大,ES6 提供了更接近传统语言的写法,引入了 class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。

    es6 class 与es5的面向对象的区别:

    1. 写法不同,使用关键字class

    2.当new一个实例,默认有一个constructor方法,且默认返回实例对象(this),也可以返回另一对象

    3.类的所有方法都在prototype属性上,但是不可枚举,且每方法结束不能使用分号

    4.类的调用必须通过new 一个实例,且类的内部默认使用严格模式

    5.不存在变量提升,必须先声明,再调用

    6.class的this 默认指向当前类

    7.class 的静态方法,使用关键字static,不需new,直接通过类来调用

    1. 实例属性和静态属性的写法,实例属性在类的内部直接使用等式(=)写法,也可以写在constructor 方法里,静态属性只需在实例属性前加一个关键字static即可

    9.类的继承使用关键字extends,继承机制与es5完全不同,

    es5的继承原理:先new子类的实例对象this,再通过将父类的方法和属性添加到子类的this上(parents.call(this))。

    Es6的继承原理:先创造父类的实例对象this,所以要构造函数constructor()访问父类的属性使用this,必须先调用super()方法;再通过子类的constructor()来修改this

    10.类的继承可以继承原生的构造函数,es5不可以

    1. 一般写法(es5 与es6)
    //一.ES5写法:
    function Animate(name){
      this.name = name;
    }
    Animate.prototype.getname = function(){
      console.log(this.name)
    }
    var p =new Animate("lity");
    p.getname();
     
    //二.ES6,面向对象的写法,calss,
    class Person{
      //constructor():构造方法是默认方法,new的时候回自动调用,如果没有显式定义,会自动添加
      //1.适合做初始化数据
      //2.constructor可以指定返回的对象
      constructor(name,age){
         this.name = name;
         this.age = age;
      }
      getval(){
        console.log(`你是${this.name},${this.age}岁`);
      }
    }      
    var c1 = new Person("lity",20); 
    c1.getval();
    

    前端全栈学习交流圈:866109386,面向1-3经验年前端开发人员,帮助突破技术瓶颈,提升思维能力,群内有大量PDF可供自取,更有干货实战项目视频进群免费领取。

    ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到

    注意 :class 类的本质还是一个函数,类本身就指向构造函数。

    typeof Person  //function
    Person === Person.prototype.constructor // true
    

    我们使用Object的一些属性或者方法检测一下 用es6 写的实例对象

    //1.查看实例对象c1的__proto__是否指向Person的原型(Person.prototype)
     console.log(c1.__proto__==Person.prototype)//true
     console.log(c1.__proto__)//原型对象的所有方法
     //2.isPrototypeOf:检测实例对象是否是某个函数的原型
      console.log(Person.prototype.isPrototypeOf(c1));//true
    //3.constructor:查看某个对象的构造函数
       console.log(c1.constructor);
     //4.hasOwnProperty:检测某个属性是否是自己的属性;不是原型对象上的属性和方法
       console.log(c1.hasOwnProperty("name"))//true;
     //5.in:通过in可以检测属性是否在自己中(this)或者是原型中存在
        console.log("getval" in c1)//原型上存在,true
        console.log("name" in c1)//constructor(自己上存在),true
     //6.自定义检测属性是否是存在
        function hasproperty(attr,obj){
           return obj.hasOwnProperty(attr)&&(attr in obj);
        }
        console.log(hasproperty("name",c1));//true;
    

    2.表达式写法

    //class表达式
    const Myclass = class Me{//这里的Me是没有作用的
      constructor(name,jog){
        this.name = name;
        this.jog = jog;
      }
      getval(){
        console.log(`name is ${this.name},job is a ${this.jog}`);
      }
    }
     var obj1 = new Myclass("lylt","teacher");
     obj1.getval();
    

    3.class的私有方法(ES6不提供写法)和私有属性(也不提供写法,提案用#识别)

      所谓私有方法和私有属性,是指只能在类的内部使用,不能在类外部调用
    

    4.ES6规定Class类没有静态属性,只有静态方法:static

     所谓静态,不需要实例化对象,直接调用
    
    class Foo {
       static classMethod() {
          return 'lity';
        }
     }
     console.log(Foo.classMethod()) // 'hello'
    

    5.new.target属性

    new是在构造函数生成实例的命令,ES6为new提供了一个属性.target,

    返回通过new 命令实例对象的class(构造函数),一般用于类的内部

    //ES5:原始写法对象
    function objtarge(name){
      if(new.target==undefined){
        throw new Error("必须实例化对象");
      }else{
        this.name = name
      }
    }
    var targets = new objtarge("litys");
    console.log(targets.name);//litys
    //es6写法:class内部使用new.target,返回当前的calss
    class caltartget{
      constructor(name){
        console.log(new.target==caltartget);//true
        if(new.target!==caltartget){
          throw new Error("实例化对象不是caltrget");
        }else{
          this.name = name;
        }
      }
    }
    var caltart = new caltartget("lity");
    console.log(caltart.name);//lity
    

    前端全栈学习交流圈:866109386,面向1-3经验年前端开发人员,帮助突破技术瓶颈,提升思维能力,群内有大量PDF可供自取,更有干货实战项目视频进群免费领取。

    6.this指向

    类的方法内部如果含有this,它默认指向类的实例。但是,必须非常小心,一旦单独使用该方法,很可能报错

    如下示例

    class Logger {
     printName(name = 'there') {
      this.print(`Hello ${name}`);
     }
     print(text) {
      console.log(text);
     }
    }
    const logger = new Logger();
    const { printName } = logger;
    printName(); // TypeError: Cannot read property 'print' of undefined
    

    分析以上示例:prinName 的方法中this,默认指向 类Logger,但是将改方法单独调用,就会报错,this会指向所在运行的环境,所以因为找不到this.print()方法而报错。

    针对以上解决this指向的方法:

    (1). 使用bind(this)

    (2). 使用es6 的箭头函数 ()=>{}

    (3).使用Proxy 代理

    //1.bind()方法
    class Logger {
     constructor() {
      this.printName = this.printName.bind(this);
     }
     // ...
    }
    //2.箭头函数 ()=>{}
    class Logger {
     constructor() {
      this.printName = (name = 'there') => {
       this.print(`Hello ${name}`);
      };
     }
     // ...
    }
    //3. Porxy()
    .................
    

    7.class 的get() 和set() 方法

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

    class MyClass {
     constructor() {
      // ...
     }
     get prop() {// 使用 get 拦截了该方法的返回值
      return 'getter';
     }
     set prop(value) {//当对该方法赋值时能获取到该赋值
      console.log('setter: '+value);
     }
    }
    let obj = new MyClass();
    obj.prop = 123;
    // setter: 123
    inst.prop
    // 'getter'
    

    前端全栈学习交流圈:866109386,面向1-3经验年前端开发人员,帮助突破技术瓶颈,提升思维能力,群内有大量PDF可供自取,更有干货实战项目视频进群免费领取。

    8.继承

    Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。

    //es5 的继承
    //父类
    function Person(name,sex){
      this.name = name;//属性
      this.sex = sex;//属性       
    }
    //定义一个原型方法
    Person.prototype.show = function(){
      console.log("我的姓名是"+this.name+"==="+"我的性别是"+this.sex)
    }
    //子类
    function Worker(name,sex,job){      
      //构成函数伪装:使用call()方法绑定this,伪装继承父级的属性
      Person.call(this,name,sex);
      this.job = job;
    }
    //继承父类的原型方法:(介绍三种方法)
    //写法一:通过遍历父级的原型一个个赋给子级的原型(es5 的原型是可枚举的,es6的不可以枚举)
    (var i in Person.prototype){
      Worker.prototype[i] = Person.prototype[i];
    }
    //写法:重新new一个父级对象赋给子级的原型
    Worker.prototype = new Person();
    Worker.prototype.constructor = Worker;
    //写法三:创建一个原型对象赋给子级的原型;(es5 推荐)
    Worker.prototype = Object.create(Person.prototype);
    Worker.prototype.constructor = Worker;
    var workers = new Worker("小明","男","job")
    //es6 的继承
    class Person{
      constructor(name,sex){
        this.name = name;//属性
         this.sex = sex;//属性
       }
    }
    class Worker extends Person{
       constructor(name,sex,job){
         super();
         this.job =job;
       }
    }
    var workers = new Worker("小明","男","job")
    

    8.1:super关键字:在子类中不同情况用法不同,既可以当作函数使用,也可以当作对象使用。

    (1):super作为函数,只能在constructor中使用:代表父类,返回子类的this
    

    (2):super作为对象,在普通函数中,cuper指向父类的原型对象,可以访问原型对象的属性和方法,注意,父类的实例的属性和方法是访问不了的

    (3):super作为对象,在静态方法中,cuper指向的是父类,不是父类的原型对象

    示例分析如下:

    //父类
    class Aniamte{
      constructor(){
        if(new.target == Aniamte){
          throw new Error("本类不能实例化,只能有子类继承");
        }
      }
      //静态方法
      static getval(mgs){
        console.log("父类的static",mgs)
      }
      //普通方法      
      setname(){
        console.log("该方法有子类重写")
      }      
    }
    //子类
    class Dog extends Aniamte{
      constructor(){
        super();//调用此方法,this才用可以用,代表父类的构造函数,返回的却是子类
        //super() ==父类.prototype.constructor.call(子类/this)
        console.log(this)//Dog {}
        this.age = 20;
        }
      //静态方法,super在静态方法中作为对象使用,指向父类;
      static getval(mgs){
        super.getval(mgs)//父类的static niceday
        console.log("子类的static",mgs)//子类的static niceday
      }
      setname(name){
        //普通方法,super作为对象使用,指向父类的原型对象,父类.prototype;
        super.setname();//该方法有子类重写
        this.name = name;
        return this.name
      }
    };
    Dog.getval("niceday");//静态方法,直接调用
    //var parAni = new Aniamte();//报错
    var dogs = new Dog();//new 一个示例对象
    dogs.setname("DOYS");////DOYS
    

    8.2.原生构造函数的继承,ES5不支持,ES6利用extend可以继承原生构造函数

    //ESMAScript的构造函数有以下几种
    /* Boolean()
    * Unmber()
    * String()
    * Array()
    * Date()
    * Function()
    * RegExp()
    * Error()
    * Object()
    */
    //实例一:自定义类Myarray 继承了原生的数组的构造函数,拥有原生数组的属性和方法了
    class Myarray extends Array{
      constructor(){
      super();
      console.log(this.constructor.name)//Myarray
      }
    }
    var myarr = new Myarray();
    console.log(Object.prototype.toString.call(myarr));//[object Array]
    myarr.push(1,2,1);
    console.log(myarr.length)//3
    

    相关文章

      网友评论

        本文标题:es6之class 基本用法解析

        本文链接:https://www.haomeiwen.com/subject/znoocqtx.html