es6新特性之 class 基本用法

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

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

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

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

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

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

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

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

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

 8. 实例属性和静态属性的写法,实例属性在类的内部直接使用等式(=)写法,也能够写在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();

 

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

注意 :class 类的本质仍是一个函数,类自己就指向构造函数。this

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

 

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

//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.表达式写法spa

//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不提供写法)和私有属性(也不提供写法,提案用#识别)prototype

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

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

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

 

5.new.target属性code

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

 

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 同样,在“类”的内部可使用getset关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。

 

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'

 

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

 

 
完结。。。谢谢
相关文章
相关标签/搜索