[JS] JavaScript 類別(Class) | PJCHENder 未整理筆記

文章推薦指數: 80 %
投票人數:10人

[JS] JavaScript 類別(Class). function constructor 有hoisting 的情況,所以可以寫再後面但在前面使用;但是class constructor 沒有hoisting 的 ... Skiptomaincontent這個網站放置的是未發佈或未完整整理的筆記內容,若想檢視正式的筆記內容請到PJCHENder那些沒告訴你的小細節。

PJCHENderOfficialDocsBlogGitHubFacebookLinkedinSearch🏠JavaScript[JS]classOnthispagefunctionconstructor有hoisting的情況,所以可以寫再後面但在前面使用;但是classconstructor沒有hoisting的情況,所有使用該classconstructor的程式,必須放在classconstructor後面。

ES6ClassPlayground@jsfiddlekeywords:class,constructor(data)​建立Constructor​傳統functionconstructor​過去使用functionconstructor來建構物件,並且搭配prototype來建議物件可使用的方法://過去使用functionconstructorletPerson=function(data){this.name=data.name;this.age=data.age;letprofile=`${this.name}(${this.age})`;//無法在實例中使用};Person.prototype.greet=function(){console.log(`Hello${this.name},yourageis${this.age}`);};letAaron=newPerson({name:'Aaron',age:28});letJackson=newPerson({name:'Jackson',age:24});console.log(Aaron);//Person {name:"Aaron",age:28}Copy在實例中取用不存在的變數時會得到undefined。

ES6Class​在ES6中可使用關鍵字class和constructor(self)://在ES6中可以透過class來建立constructorclassPerson{constructor(data){this.name=data.name;this.age=data.age;}}letAaron=newPerson({name:'Aaron',age:28});letJackson=newPerson({name:'Jackson',age:24});console.log(Aaron);//Person {name:"Aaron",age:28}Copy設定預設值://同樣可以透過objectdestructuring來做到設定預設值classPerson{constructor({name,age=18}={}){this.name=name;this.age=age;}}letAaron=newPerson({name:'Aaron'});letJackson=newPerson({name:'Jackson',age:24});console.log(Aaron);//Person {name:"Aaron",age:18}console.log(Jackson);//Person {name:"Jackson",age:24}Copy在class中只能使用方法(function),不能直接代入資料。

Prototypemethod(原型方法)​原型方法(prototypemethod)指的是這些方法是建立來讓該類別的實例(instance)使用的。

直接在建構式(constructor)中建立函式就是原型方法:classStudent{constructor(firstName,lastName){//this指稱的是所建立的instancethis.firstName=firstName;this.lastName=lastName;}//原型方法getName(){//this指稱的是所建立的instancereturn`${this.firstName}${this.lastName}`;}}//類別的實力可以直接使用原型方法aaron=newStudent('Aaron','Chen');console.log(aaron.getName());//AaronChenCopyStaticmethod(靜態方法)​keywords:static​staticmethod只存在class中,不能被instance所提取,只能透過指稱到該class才能使用該方法,可以透過static這個關鍵字來建立staticmethod:靜態方法(staticmethod)指的是該方法只能用在該class上,而不能用在instance上。

第一種方式:在static中使用this​在static中使用this,在使用staticmethod時搭配call來指定this的對象://呼叫靜態方法的第一種方式classBird{constructor({color='red'}={}){this.color=color;}//使用static以建立staticmethod,裡面用thisstaticchangeColor(color){//this原本指稱的是所建立的Bird這個Class//但在呼叫這個方法時,使用了call()把this改成了指定的instancethis.color=color;}}letredBird=newBird();console.log(redBird.color);//red//redBird.changeColor('blue')//redBird.changeColorisnotafunctionBird.changeColor.call(redBird,'blue');console.log(redBird.color);//blueCopy第二種方式:在static中不使用this​在static中沒有使用this,需要在參數中代入要指稱的對象://呼叫靜態方法的第二種方式classBird{constructor({color='red'}={}){this.color=color;}staticchangeColor(bird,color){//this原本指稱的是所建立的Bird這個Classbird.color=color;}}letredBird=newBird();console.log(redBird.color);//red//redBird.changeColor('blue')//redBird.changeColorisnotafunctionBird.changeColor(redBird,'blue');console.log(redBird.color);//blueCopySetter和Getter​keywords:get,set​gettermethod是在class中沒有帶參數就可以回傳值的方法,可以透過get設定;settermethod則是可以透過=來對物件賦值,可以使用set來設定:classPerson{constructor({firstName,lastName,country='Taiwan'}={}){this.firstName=firstName;this.lastName=lastName;this.country=country;}//gettermethodgetname(){returnthis.firstName+''+this.lastName;}//settermethodsetname(input){[this.firstName,this.lastName]=input.split('');}}letaaron=newPerson({firstName:'Aaron',lastName:'Chen'});console.log(aaron.name);//使用gettermethod,AaronChenaaron.name='PeterChen';//使用settermethodconsole.log(aaron.name);//PeterChenCopy使用subclass​keywords:extends,super​繼承自另一個class時需要使用關鍵字extendssubclass有可能覆蓋掉superclass的methodsuper的用法就像是去呼叫它的superclass這個ClassclassPerson{constructor({name,age=18}={}){this.name=name;this.age=age;}dance(){console.log('olddance');}}classStudentextendsPerson{constructor({name,age,interestLevel=5}={}){//因為這是extendsfromPerson,所以我們必須要在為instance賦值前,//在Studentconstructor裡面呼叫superfunction,//呼叫superfunction的意思就是呼叫Person的constructorfunction。

super({name,age});this.name=name;this.age=age;this.interestLevel=interestLevel;this.grades=newMap();}//如果traditional=true,則使用Person的dance();否則...//也就是說,subclass是可以覆蓋superclass的methoddance(traditional){if(traditional){super.dance();//呼叫Person的dancemethod}else{constdances=['lyrical','tap','ballet','jaz'];console.log(`${this.name}isdoingthe${dances[Math.floor(Math.random()*dances.length)]}!`,);}}}letstevenJ=newStudent({name:'Steven',age:22});stevenJ.grades.set('Math',10);stevenJ.dance();console.log(stevenJ);console.log(`stevenJ'sinterestLevelis:${stevenJ.interestLevel}`);CopyClassfieldssyntax:public/privateclassfields​Classfields@Googledeveloper在Java中物件的屬性(property)會稱作field。

Public,Private,Static的差別:Publicvariable:class內的變數可以被instance所存取和修改Privatevariable:class內的變數無法被instance所存取和修改Staticvariable/staticmethod:靜態表示該方法或變數,需要透過呼叫Class才能取得或使用。

在原本的ES6JavaScriptclass語法中,並沒有辦法定義私有變數(privatevariable),雖然慣例上會使用_作為這些變數的開頭,但實際上開發者可以直接存取和修改這些變數。

例如:classIncreasingCounter{constructor(){this._count=0;}//...}constcounter=newIncreasingCounter();//雖然概念上希望_count是私有變數,但實際上可以直接對這個值進行存取和修改counter._count;counter._count=42;CopyPublicclassfields​在新的publicclassfields則可以讓我們簡化對於類別的定義,也就是可以直接在class中定義變數,但此時_count仍是公開的屬性(publicproperty):classIncreasingCounter{_count=0;getvalue(){console.log('Gettingthecurrentvalue!');returnthis._count;}increment(){this._count++;}}CopyPrivateclassfields​為了解決最初希望有privatevariable的情況,多了一種privateclassfields的語法,你只需要在變數名稱的最前方加上#即可:classIncreasingCounter{#count=0;getvalue(){console.log('Gettingthecurrentvalue!');returnthis.#count;}increment(){this.#count++;}}Copy如此,#count這個變數將無法在class內部以外的其他地方被存取:constcounter=newIncreasingCounter();counter.#count;//→SyntaxErrorcounter.#count=42;//→SyntaxErrorCopyStaticandpublic/privateproperties​透過classfieldsyntax的寫法,一樣可以用來建立公開(public)或私有(private)的靜態屬性(staticproperty)或靜態方法(staticmethod):classFakeMath{//`PI`是一個靜態的公開屬性//`PI`isastaticpublicproperty.staticPI=22/7;//Closeenough.//`#totallyRandomNumber`是一個靜態的私有屬性static#totallyRandomNumber=4;//`#computeRandomNumber`是一個靜態的私有方法static#computeRandomNumber(){returnFakeMath.#totallyRandomNumber;}//`random`是一個靜態的公開方法(ES2015syntax)//thatconsumes`#computeRandomNumber`.staticrandom(){console.log('Iheardyoulikerandomnumbers…');returnFakeMath.#computeRandomNumber();}}FakeMath.PI;//→3.142857142857143FakeMath.random();//logs'Iheardyoulikerandomnumbers…'//→4FakeMath.#totallyRandomNumber;//→SyntaxErrorFakeMath.#computeRandomNumber();//→SyntaxErrorCopySimplersubclassing​見Simplersubclassing@GoogleDevelopers-Classfieldssyntaxcodestyle​不建議使用getter和setter,因為它可能會發生無預期的副作用,並且難以測試與維護;如果需要,使用原型方法(prototypemethod)自己建立,例如getVal()和setVal('Hello')。

24.2@airbnb參考​Classes@MDN>WebtechnologyfordevelopersES6InDepth:Classes@MozillaHacksES6InDepth:Subclassing@MozillaHacksClasses@ExploringES6Publicclassfields/Privateclassfields​Publicandprivateclassfields@GoogleDevelopersESproposal:classfields@2alityPrevious[JS]asyncanddeferattributesNext[JS]closure建立Constructor傳統functionconstructorES6ClassPrototypemethod(原型方法)Staticmethod(靜態方法)第一種方式:在static中使用this第二種方式:在static中不使用thisSetter和Getter使用subclassClassfieldssyntax:public/privateclassfieldsPublicclassfieldsPrivateclassfieldsStaticandpublic/privatepropertiesSimplersubclassingcodestyle參考Publicclassfields/Privateclassfields



請為這篇文章評分?