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

 

 
完結。。。謝謝
相關文章
相關標籤/搜索