JavaScript Class類實例講解
Class類
ES6提供了更接近傳統(tǒng)語言的寫法,引入了Class(類)這個概念,作為對象的模板。通過class關(guān)鍵字,可以定義類。基本上,ES6的class可以看作只是一個語法糖,它的絕大部分功能,ES5都可以做到,新的class寫法只是讓對象原型的寫法更加清晰,更像面向?qū)ο缶幊痰恼Z法。
初識class
之前ES5通過構(gòu)造函數(shù)實現(xiàn)實例化的方法
<script> // 定義人類 function People(name,age){ this.name = name this.age = age } // 添加方法 People.prototype.say = function (){ console.log('hello world'); } // 實例化方法 let person = new People('張三',18) person.say()//hello world console.log(person);//People {name: '張三', age: 18} </script>
ES6 class方法實現(xiàn)
constructor()方法是類的默認(rèn)方法,通過 new 命令生成對象實例時,自動調(diào)用該方法,一個類必須有constructor()方法,如果沒有顯示定義,一個空的constructor()方法會被默認(rèn)添加。
<script> // class class People { // 構(gòu)造方法 名字是固定格式不能修改 constructor(name,age){ this.name = name this.age = age } // 方法必須使用該語法,不能使用 ES5 的對象完整形式 say(){ console.log('hello world'); } } // 實例化對象 let person = new People('張三',18) person.say()//hello world console.log(person);//People {name: '張三', age: 18} </script>
class中g(shù)etter和setter設(shè)置
在ES6中,類的內(nèi)部可以使用 getter (取值函數(shù)) 和 setter (存值函數(shù)) 關(guān)鍵字,即 get 和 set ,對某個屬性設(shè)置取值函數(shù)和存值函數(shù),攔截該函數(shù)的存取行為。
<script> class People { get name(){ console.log('我是張三'); return '這是我的名字'//如果不寫return,默認(rèn)是undefined } set name(Name){//形參必須有 console.log('我的名字被修改了'); } } // 實例化對象 let p = new People() // 只要讀取 p 的實例化屬性,就會執(zhí)行 get 關(guān)鍵字函數(shù)里面代碼,而且這個函數(shù)的返回值就是屬性的一個值 console.log(p.name); // 只要對 name 屬性進(jìn)行一個修改,如果有set關(guān)鍵字函數(shù),就會執(zhí)行該函數(shù) p.name = 'f' </script>
表達(dá)式方式書寫
和函數(shù)一樣,類可以用表達(dá)式定義書寫,需要注意的是:定義的類名只能在Class內(nèi)部使用,指代當(dāng)前類,在Class外部,類只能用自己定義等于類的常量。
<script> const myClass = class Me { getClass(){ return Me.name//返回類名 } } let c = new myClass() console.log(c.getClass())//Me Me.name//Me is not defined // 如果類的內(nèi)部沒用到的話,可以省略Me,也就是可以寫成下面的形式 const MyClass = class {}; </script>
靜態(tài)屬性與靜態(tài)方法
靜態(tài)屬性是指 Class 本身的屬性,即 Class.propName,而不是定義在實例對象 this 上的屬性。
實例對象和函數(shù)對象的屬性是不相通的,實例對象的屬性和構(gòu)造函數(shù)的原型對象相通,實例對象只能繼承構(gòu)造函數(shù)原型中的屬性和方法。
<script> function People(){ } // 函數(shù)屬性和方法 People.name = '張三' People.say = function(){ console.log('hello world'); } // 原型對象屬性和方法 People.prototype.age = 18 // 實例化對象 let p = new People() console.log(People.name,People.say()); console.log(p.age); console.log(p.name,p.say()); </script>
以class方法展示,因為ES6明確規(guī)定,Class內(nèi)部只有靜態(tài)方法,沒有靜態(tài)屬性,而要想得到設(shè)置靜態(tài)屬性,需要在實例屬性前面加上 static 關(guān)鍵字;靜態(tài)方法也要加上 static 關(guān)鍵字,表示該方法不會被實例繼承,而是直接通過類來調(diào)用。
<script> class People { // 靜態(tài)屬性 static name = '張三' static say(){ console.log('hello world'); } } let p = new People() console.log(p.name);//undefined console.log(People.name);//張三 </script>
私有屬性和私有方法
常見需求:私有屬性和方法,是只能在類內(nèi)部訪問的屬性和方法,外部不能訪問,有利于代碼的封裝。
ES6中正式為class添加了私有屬性和方法,方法是在屬性和方法名之前使用 # 表示,如果不帶 # ,會被當(dāng)作另一個屬性和方法。
<script> class person { // 私有屬性 #name constructor(name){ this.#name = name } // 私有方法 #sayName(){ return this.#name } result(){ console.log(this.#name); } } let p = new person() p.result = '張三' console.log(p);//person {result: '張三', #sayName: ?, #name: undefined} p.#name//報錯 </script>
當(dāng)我們想判斷某個類的私有屬性是否存在時,我們可以用 in 運算符進(jìn)行判斷。
<script> class A { #foo = 0; m() { console.log(#foo in this); // true console.log(#bar in this); // Private field '#bar' must be declared in an enclosing class(提示我們:私有字段“#bar”必須在封閉類中聲明) } } let a = new A() a.m() </script>
class繼承
構(gòu)造函數(shù)實現(xiàn)繼承
通過原型鏈進(jìn)行繼承,如果有不熟悉原型鏈的朋友,可以看一下我之前的文章:原型和原型鏈
<script> // 動物 function Animals(name,age){ this.name = name this.age = age } Animals.prototype.call = function(){ console.log('我是動物'); } // 狗 function Dog(name,age,color,gender){ // 改變this的指向,繼承父類 Animals.call(this,name,age) this.color = color this.gender = gender } // 設(shè)置子類構(gòu)造函數(shù)的原型 Dog.prototype = new Animals //此時子類的實例對象就會繼承父類上面的方法 Dog.prototype.constructor = Dog // 聲明子類的方法 Dog.prototype.say = function(){ console.log('汪汪汪!??!'); } // 子類對象進(jìn)行實例化 const d = new Dog('小明',3,'棕色','雄') console.log(d); </script>
class類實現(xiàn)繼承
class可以通過 extends 關(guān)鍵字實現(xiàn)繼承,讓子類繼承父類屬性和方法,可以看出 extends 的寫法比上文 原型鏈繼承 清晰方便的多。
<script> class Animals { // 構(gòu)造方法 constructor(name,age){ this.name = name this.age = age } // 父類成員的屬性 call(){ console.log('我是動物'); } } class Dog extends Animals { // 構(gòu)造方法 constructor(name,age,color,gender){ // 調(diào)用父類方法,需要用super(),super()就是父類的constructor()方法 super(name,age) this.color = color this.gender = gender } // 子類獨有的方法 say(){ console.log('汪汪汪?。。?); } // 當(dāng)子類和父類重名時,優(yōu)先調(diào)用的是子類的方法 call(){ console.log('我也是動物'); // 如果想調(diào)用父類方法,使用如下語句:super.父類方法() super.call() } } // 實例化子類對象 const d = new Dog('小明',3,'棕色','雄') console.log(d); d.call() d.say() </script>
super 關(guān)鍵字
上面代碼用到 super 這個關(guān)鍵字,這里簡單說明一下:子類繼承父類的 constructor() 構(gòu)造函數(shù)中必須要有 super(),代表調(diào)用父類的構(gòu)造函數(shù),沒有就會報錯,super雖然代表父類的構(gòu)造函數(shù),但是返回的是子類的實例,即super內(nèi)部的this指的是子類的實例。作為函數(shù)時,super() 只能用在子類的構(gòu)造函數(shù)中,用在其他地方就會報錯。
判斷繼承是否存在
Object.getPrototypeOf()方法可以用來從子類上獲取父類,所以可以用來判斷一個類是否繼承另一個類。
<script> class people {} class boy extends people {} console.log(Object.getPrototypeOf(boy) === people);//true </script>
靜態(tài)屬性和方法繼承
父類的靜態(tài)屬性和方法也能被子類繼續(xù),如下:
<script> class people { // 父類靜態(tài)屬性 屬性為數(shù)值 static age = 18 // 父類靜態(tài)屬性 屬性為對象 static h = {height:180} // 父類靜態(tài)方法 static say(){ console.log('hello world'); } } // 子類繼承父類 class boy extends people { constructor(){ // 調(diào)用父類的構(gòu)造函數(shù) super() // boy類繼承靜態(tài)屬性時,會采用淺拷貝,拷貝父類靜態(tài)屬性的值,因此people.age和boy.age是兩個彼此獨立的屬性。 boy.age-- // 如果父類的靜態(tài)屬性的值是一個對象,那么子類的靜態(tài)屬性也會指向這個對象,因為淺拷貝只會拷貝對象的內(nèi)存地址所以,子類修改這個對象的屬性值,會影響到父類。 boy.h.height-- } } // 實例化子類 let b = new boy() boy.say() console.log(people.age); console.log(boy.age); console.log(boy.h.height); console.log(people.h.height); console.log(b); </script>
私有屬性和方法繼承
私有屬性和方法只能定義在它本身的class里面使用,所以子類會繼承父類所有的屬性和方法除了私有屬性和方法,那么如何讓子類訪問到父類中的私有屬性和方法呢?如果父類定義了私有屬性的讀寫方法,子類就可以通過這些方法,讀取私有屬性。
<script> class people { #name = '張三' // 定義用來讀取私有屬性和方法的函數(shù) getName(){ return this.#name } } class boy extends people { constructor(){ // 調(diào)用父類的構(gòu)造函數(shù) super() console.log(this.getName());//張三 } } let b = new boy() </script>
class顯示原型與隱式原型關(guān)系
每個對象都有隱式原型 __proto__ 屬性,指向?qū)?yīng)的構(gòu)造函數(shù)的顯示原型 prototype 屬性,class作為構(gòu)造函數(shù)的語法糖,同時也具有 prototype 屬性和 __proto__ 屬性,所以存在兩條繼承鏈。當(dāng)然這里這做一個了解。
<script> class people {} class boy extends people{} // 子類的__proto__屬性,表示構(gòu)造函數(shù)的繼承,總是指向父類。 console.log(boy.__proto__ === people); // true // 子類prototype屬性的__proto__屬性,表示方法的繼承,總是指向父類的prototype屬性。 console.log(boy.prototype.__proto__ === people.prototype); // true </script>
到此這篇關(guān)于JavaScript Class類實例講解的文章就介紹到這了,更多相關(guān)JS Class類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信小程序怎么加入JavaScript腳本,做出動態(tài)效果
這篇文章主要介紹了教大家為小程序加入?JavaScript?腳本,做出動態(tài)效果,以及如何跟用戶互動。學(xué)會了腳本,就能做出復(fù)雜的頁面了。需要的朋友可以參考下2022-12-12開源免費天氣預(yù)報接口API及全國所有地區(qū)代碼(國家氣象局提供)
這篇文章主要介紹了開源免費天氣預(yù)報接口API及全國所有地區(qū)代碼(國家氣象局提供)的相關(guān)資料,需要的朋友可以參考下2016-12-12JS利用原生canvas實現(xiàn)圖形標(biāo)注功能
這篇文章主要為大家詳細(xì)介紹了JS如何利用原生canvas實現(xiàn)圖形標(biāo)注功能,支持矩形、多邊形、線段、圓形等已繪制的圖形進(jìn)行縮放,移動,需要的可以參考下2024-03-03js window.print實現(xiàn)打印特定控件或內(nèi)容
window.print可以打印網(wǎng)頁,但有時候我們只希望打印特定控件或內(nèi)容,怎么辦呢?可以把要打印的內(nèi)容放在div中,然后用下面的代碼進(jìn)行打印,希望對大家有所幫助2013-09-09