成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

ES6—class與面向?qū)ο缶幊蹋?)

wangjuntytl / 2907人閱讀

摘要:接下來我們看下類的寫法,這個(gè)就很接近于傳統(tǒng)面向?qū)ο笳Z言了。如果你想了解傳統(tǒng)面向?qū)ο笳Z言,這里是一個(gè)好切入點(diǎn)。作為對(duì)象時(shí),指向父類的原型對(duì)象。這些就是為將來在中支持面向?qū)ο蟮念悪C(jī)制而預(yù)留的。

在ES5中,我們經(jīng)常使用方法或者對(duì)象去模擬類的使用,并基于原型實(shí)現(xiàn)繼承,雖然可以實(shí)現(xiàn)功能,但是代碼并不優(yōu)雅,很多人還是傾向于用 class 來組織代碼,很多類庫、框架創(chuàng)造了自己的 API 來實(shí)現(xiàn) class 的功能。

ES6 時(shí)代終于有了 class (類)語法,能讓我們可以用更簡(jiǎn)明的語法實(shí)現(xiàn)繼承,也使代碼的可讀性變得更高,同時(shí)為以后的JavaScript語言版本添加更多的面向?qū)ο筇卣鞔蛳禄A(chǔ)。有了ES6的class 以后媽媽再也不用擔(dān)心我們的代碼亂七八糟了,這簡(jiǎn)直是喜大普奔的事情。ok,我們看看神奇的class.

一、 類的定義

1.1 ES5 模擬類定義

function Person( name , age ) {
    this.name = name;
    this.age = age;
}
Person.prototype.say = function(){
    return "我叫" + this.name + ",今年" + this.age + "歲";
}
var  p = new Person("大彬哥",18);  // Person?{name: "大彬哥", age: 18}
p.say()                           //"我叫大彬哥,今年18歲"

使用ES5語法定義了一個(gè)Person類,該類有name和age兩個(gè)屬性和一個(gè)原型say方法。

這種寫法跟傳統(tǒng)的面向?qū)ο笳Z言(比如 C++ 和 Java)差異很大。接下來我們看下ES6 類的寫法,這個(gè)就很接近于傳統(tǒng)面向?qū)ο笳Z言了。如果你想了解傳統(tǒng)面向?qū)ο笳Z言,這里是一個(gè)好切入點(diǎn)。

1.2 ES6 class類定義

class Person {
  constructor( name , age ) {
    this.name = name;
    this.age = age;
  }
  say() {
    return "我叫" + this.name + ",今年" + this.age + "歲";
  }
}
var  p = new Person("大彬哥",18);  // Person?{name: "大彬哥", age: 18}
p.say()                           //"我叫大彬哥,今年18歲"

上面代碼定義了一個(gè)同樣的Person類,constructor方法就是構(gòu)造方法,而this關(guān)鍵字則代表實(shí)例對(duì)象,這更接近傳統(tǒng)語言的寫法。

注意:

雖然引入了class關(guān)鍵字,但ES6中并沒有真的引入類這個(gè)概念,通過class定義的仍然是函數(shù):

console.log(typeof Person); // "function"

所以說,class僅僅是通過更簡(jiǎn)單直觀的語法去實(shí)現(xiàn)原型鏈繼承。這種對(duì)語言功能沒有影響、但是給程序員帶來方便的新語法,被稱為語法糖。


二、類的傳參 constructor

在類的參數(shù)傳遞中我們用constructor( )進(jìn)行傳參。傳遞參數(shù)后可以直接使用this.xxx進(jìn)行調(diào)用。

class Person {
   constructor(a,b){
        this.a=a;
        this.b=b;
   }
   add(){
        return this.a + this.b;
   }
}
let p = new Person(18,30);
console.log(p.add());  // 48 (18+30)

我們用constructor來傳遞參數(shù),然后用了一個(gè)add方法,把參數(shù)相加。這和以前我們的函數(shù)傳參方法有些不一樣,所以小伙伴們要注意轉(zhuǎn)換下思維。

三、靜態(tài)方法

在面向?qū)ο笳Z言中,靜態(tài)方法是指不需要實(shí)例化,可以通過類名直接調(diào)用的方法,但靜態(tài)方法不會(huì)繼承到類實(shí)例中,因此靜態(tài)方法經(jīng)常用來作為工具函數(shù)。比如我們經(jīng)常用的Math.random(),我們并不需要先new 一個(gè)Math然后再去用,一是如果作者那么設(shè)計(jì)JS一來是沒必要,二是用起來太繁瑣。

在使用函數(shù)模擬類時(shí),可以像下面這樣定義靜態(tài)方法:

function Person(name, sex) {}

Person.walk = function() {
    console.log("我會(huì)走路")
}

Person.walk();  // 我會(huì)走路
var person = new Person();
person.walk();  // TypeError

在ES6 class類定義中,可以使用static關(guān)鍵字定義:

class Person {
  constructor() {}

  static walk(){
      console.log("我會(huì)走路")
  }
}
Person.walk();  // 我會(huì)走路
var person = new Person();
person.walk();  // TypeError

static關(guān)鍵字是ES6的另一個(gè)語法糖,static 使靜態(tài)方法聲明也成為了一個(gè)一等公民。

于此同時(shí),靜態(tài)方法也是可以從子類中的super對(duì)象上調(diào)用的。

class Person {
  constructor() {}

  static walk(){
      return "我會(huì)走路"
  }
}

class People extends Person {
  static walk() {
    return super.walk() + ", 我還會(huì)跑步";
  }
}

People.walk();  //"我會(huì)走路, 我還會(huì)跑步"

四、封裝與繼承

封裝和繼承,是面向?qū)ο缶幊倘蠛诵奶卣髦蟹浅V匾膬蓚€(gè),封裝和繼承在我們實(shí)際生活中也有非常多的應(yīng)用。舉個(gè)例子,你去驢肉火燒店去吃飯。

老板把驢肉面和火燒一起買,起名字叫“精英驢火套餐”,這就是封裝。

而進(jìn)去以后跟老板說,老板給我來個(gè)“82年的驢火套餐”這就是繼承。當(dāng)然了你不僅僅能繼承,還能擴(kuò)展自己的功能。比如你可以跟老板說,老板再給我加一個(gè)驢板腸。說的我都餓了,不過我們還是教編程的專欄,不是開店的專欄,我們繼續(xù),看看ES6里面怎么玩繼承。

4.1 extends

舊的原型繼承有時(shí)看起來讓人非常頭疼。

function Child(firstName, lastName, age) {
  Parent.call(this, firstName, lastName)
  this.age = age
}

Child.prototype = Object.create(Parent.prototype)
Child.constructor = Child

ES6中新的extends關(guān)鍵字解決了這個(gè)問題:

class Child extends Parent {}

上面代碼定義了一個(gè)Child類,該類通過extends關(guān)鍵字,繼承了Parent類的所有屬性和方法。

由于沒有在Child內(nèi)部寫任何代碼,所以這兩個(gè)類完全一樣,等于復(fù)制了一個(gè)Parent類。

之后,我們?cè)贑hild內(nèi)部加上代碼:

class Child extends Parent {
  constructor(firstName, lastName, age) {
    super(firstName, lastName)  
    // 調(diào)用父類的constructor(firstName, lastName)
    this.age = age
  }
  speak(){
    return this.age + " " + super.speak(); 
    // 調(diào)用父類的speak()
  }
}

使用簡(jiǎn)介的 extends 達(dá)到繼承的目的,而非雜亂的 Object.create()、.proto、Object.setPrototypeOf(),這樣能讓我們更順利的擴(kuò)充功能。

4.2 super

super這個(gè)關(guān)鍵字,既可以當(dāng)作函數(shù)使用,也可以當(dāng)作對(duì)象使用。在這兩種情況下,它的用法完全不同。

(1)super作為函數(shù)調(diào)用

代表父類的構(gòu)造函數(shù),ES6中規(guī)定,子類的構(gòu)造函數(shù)必須執(zhí)行一次super函數(shù)。

class A {}

class B extends A {
  constructor() {
    super();
  }
}

上面代碼中,子類B的構(gòu)造函數(shù)之中的super(),代表調(diào)用父類的構(gòu)造函數(shù),這是必須的,否則 JavaScript 引擎會(huì)報(bào)錯(cuò)。

注意,super雖然代表了父類A的構(gòu)造函數(shù),但是返回的是子類B的實(shí)例,即super內(nèi)部的this指的是B,因此super()在這里相當(dāng)于A.prototype.constructor.call(this)。

(2)super作為對(duì)象時(shí),指向父類的原型對(duì)象。

class A {
  p() {
    return 2;
  }
}

class B extends A {
  constructor() {
    super();
    console.log(super.p()); // 2
  }
}

let b = new B();

與Java一樣,JavaScript也使用extends關(guān)鍵字實(shí)現(xiàn)繼承,子類中可以通過super關(guān)鍵字調(diào)用父類:

在 constructor 里面,super 的用法是 super()。它相當(dāng)于一個(gè)函數(shù),調(diào)用它等于調(diào)用父類的 constructor 。

但在普通方法里面,super 的用法是 super.prop 或者 super.method(),它相當(dāng)于一個(gè)指向?qū)ο蟮?[[Prototype]] 的屬性。

4.3 getter(取值函數(shù))、 setter(存值函數(shù))

與 ES5 一樣,在“類”的內(nèi)部可以使用get和set關(guān)鍵字,對(duì)某個(gè)屬性設(shè)置存值函數(shù)和取值函數(shù),攔截該屬性的存取行為。

class Person {
  constructor() {}
  get prop() {
    return "getter";
  }
  set prop(value) {
    console.log("setter: "+value);
  }
}

let p = new Person();
p.prop = 666;   // setter: 666
p.prop           // "getter"

五、總結(jié)

無論學(xué)什么知識(shí),最重要也是最基礎(chǔ)的,要實(shí)現(xiàn)思想上的轉(zhuǎn)變,目前大部分框架和庫,都采用了面向?qū)ο蠓绞骄幊獭6以诠ぷ髦?,要書寫中型和大型的?xiàng)目也經(jīng)常使用面向?qū)ο蠓绞骄幊?,可能大家?xí)慣了面向過程方式編程,其實(shí)面向?qū)ο蠓绞骄幊桃坏┝?xí)慣了,會(huì)讓我開發(fā)和思路更寬闊和易于開發(fā)項(xiàng)目。

從學(xué)習(xí)javascript基礎(chǔ)開始的時(shí)候,我們就了解了js中的保留字,js中并沒有用到,但是將來可能會(huì)用到的未來關(guān)鍵字。這些保留字中就包括:class、extends、super。這些就是為將來在js中支持面向?qū)ο蟮念悪C(jī)制而預(yù)留的。

果不其然,現(xiàn)在ES6語法中使用到了這些保留字,這些保留字成功升級(jí)成了關(guān)鍵字,可見當(dāng)時(shí)javascript的設(shè)計(jì)者還是很有前瞻眼光的。

通過這些新的關(guān)鍵字,使類成為了JS中一個(gè)新的一等公民。但是目前為止,這些關(guān)于類的新關(guān)鍵字僅僅是建立在舊的原型系統(tǒng)上的語法糖。這樣做的原因是為了保證向后兼容性。也就是,舊代碼可以在不做任何hack的情況下,與新代碼同時(shí)運(yùn)行。

不過,它使代碼的可讀性變得更高,并且為今后版本里更多面向?qū)ο蟮男绿匦源蛳铝嘶A(chǔ)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/110234.html

相關(guān)文章

  • 重新認(rèn)識(shí)JavaScript面向對(duì)象: 從ES5到ES6

    摘要:基于原型的面向?qū)ο笤诨谠偷恼Z言中如并不存在這種區(qū)別它只有對(duì)象不論是構(gòu)造函數(shù),實(shí)例,原型本身都是對(duì)象。允許動(dòng)態(tài)地向單個(gè)的對(duì)象或者整個(gè)對(duì)象集中添加或移除屬性。為了解決以上兩個(gè)問題,提供了構(gòu)造函數(shù)創(chuàng)建對(duì)象的方式。 showImg(https://segmentfault.com/img/remote/1460000013229218); 一. 重新認(rèn)識(shí)面向?qū)ο?1. JavaScript...

    VishKozus 評(píng)論0 收藏0
  • 重新認(rèn)識(shí)JavaScript面向對(duì)象: 從ES5到ES6

    摘要:基于原型的面向?qū)ο笤诨谠偷恼Z言中如并不存在這種區(qū)別它只有對(duì)象不論是構(gòu)造函數(shù),實(shí)例,原型本身都是對(duì)象。允許動(dòng)態(tài)地向單個(gè)的對(duì)象或者整個(gè)對(duì)象集中添加或移除屬性。為了解決以上兩個(gè)問題,提供了構(gòu)造函數(shù)創(chuàng)建對(duì)象的方式。 showImg(https://segmentfault.com/img/remote/1460000013229218); 一. 重新認(rèn)識(shí)面向?qū)ο?1. JavaScript...

    用戶83 評(píng)論0 收藏0
  • 前端進(jìn)擊的巨人(七):走進(jìn)面向對(duì)象,原型原型鏈,繼承方式

    摘要:除了以上介紹的幾種對(duì)象創(chuàng)建方式,此外還有寄生構(gòu)造函數(shù)模式穩(wěn)妥構(gòu)造函數(shù)模式。 showImg(https://segmentfault.com/img/remote/1460000018196128); 面向?qū)ο?是以 對(duì)象 為中心的編程思想,它的思維方式是構(gòu)造。 面向?qū)ο?編程的三大特點(diǎn):封裝、繼承、多態(tài): 封裝:屬性方法的抽象 繼承:一個(gè)類繼承(復(fù)制)另一個(gè)類的屬性/方法 多態(tài):方...

    wums 評(píng)論0 收藏0
  • 面向對(duì)象特征之封裝-Es6Class私有和受保護(hù)的屬性及方法

    摘要:熟悉面向?qū)ο缶幊痰亩贾?,面向?qū)ο缶幊套钪匾脑瓌t之一從外部接口劃分內(nèi)部接口。所以,面向?qū)ο缶幊叹皖愃朴谄囈粯印? 熟悉面向?qū)ο缶幊痰亩贾?,面向?qū)ο缶幊套钪匾脑瓌t之一 - 從外部接口劃分內(nèi)部接口。也就是說,針對(duì)某一類事物,我們其實(shí)并不是那么在乎其內(nèi)部究竟是怎樣去實(shí)現(xiàn)的,只關(guān)心怎樣使用而已。 為了理解這點(diǎn),讓我們先來看看現(xiàn)實(shí)生活中的列子。通常,我們使用的設(shè)備非常復(fù)雜。但是從外部接口界...

    neuSnail 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<