JavaScript Class類實例講解
Class類
ES6提供了更接近傳統語言的寫法,引入了Class(類)這個概念,作為對象的模板。通過class關鍵字,可以定義類?;旧希珽S6的class可以看作只是一個語法糖,它的絕大部分功能,ES5都可以做到,新的class寫法只是讓對象原型的寫法更加清晰,更像面向對象編程的語法。
初識class
之前ES5通過構造函數實現實例化的方法
<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方法實現
constructor()方法是類的默認方法,通過 new 命令生成對象實例時,自動調用該方法,一個類必須有constructor()方法,如果沒有顯示定義,一個空的constructor()方法會被默認添加。
<script>
// class
class People {
// 構造方法 名字是固定格式不能修改
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中getter和setter設置
在ES6中,類的內部可以使用 getter (取值函數) 和 setter (存值函數) 關鍵字,即 get 和 set ,對某個屬性設置取值函數和存值函數,攔截該函數的存取行為。
<script>
class People {
get name(){
console.log('我是張三');
return '這是我的名字'//如果不寫return,默認是undefined
}
set name(Name){//形參必須有
console.log('我的名字被修改了');
}
}
// 實例化對象
let p = new People()
// 只要讀取 p 的實例化屬性,就會執(zhí)行 get 關鍵字函數里面代碼,而且這個函數的返回值就是屬性的一個值
console.log(p.name);
// 只要對 name 屬性進行一個修改,如果有set關鍵字函數,就會執(zhí)行該函數
p.name = 'f'
</script>
表達式方式書寫
和函數一樣,類可以用表達式定義書寫,需要注意的是:定義的類名只能在Class內部使用,指代當前類,在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
// 如果類的內部沒用到的話,可以省略Me,也就是可以寫成下面的形式
const MyClass = class {};
</script>靜態(tài)屬性與靜態(tài)方法
靜態(tài)屬性是指 Class 本身的屬性,即 Class.propName,而不是定義在實例對象 this 上的屬性。
實例對象和函數對象的屬性是不相通的,實例對象的屬性和構造函數的原型對象相通,實例對象只能繼承構造函數原型中的屬性和方法。
<script>
function People(){
}
// 函數屬性和方法
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內部只有靜態(tài)方法,沒有靜態(tài)屬性,而要想得到設置靜態(tài)屬性,需要在實例屬性前面加上 static 關鍵字;靜態(tài)方法也要加上 static 關鍵字,表示該方法不會被實例繼承,而是直接通過類來調用。
<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>私有屬性和私有方法
常見需求:私有屬性和方法,是只能在類內部訪問的屬性和方法,外部不能訪問,有利于代碼的封裝。
ES6中正式為class添加了私有屬性和方法,方法是在屬性和方法名之前使用 # 表示,如果不帶 # ,會被當作另一個屬性和方法。
<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>當我們想判斷某個類的私有屬性是否存在時,我們可以用 in 運算符進行判斷。
<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繼承
構造函數實現繼承
通過原型鏈進行繼承,如果有不熟悉原型鏈的朋友,可以看一下我之前的文章:原型和原型鏈
<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
}
// 設置子類構造函數的原型
Dog.prototype = new Animals //此時子類的實例對象就會繼承父類上面的方法
Dog.prototype.constructor = Dog
// 聲明子類的方法
Dog.prototype.say = function(){
console.log('汪汪汪?。?!');
}
// 子類對象進行實例化
const d = new Dog('小明',3,'棕色','雄')
console.log(d);
</script>
class類實現繼承
class可以通過 extends 關鍵字實現繼承,讓子類繼承父類屬性和方法,可以看出 extends 的寫法比上文 原型鏈繼承 清晰方便的多。
<script>
class Animals {
// 構造方法
constructor(name,age){
this.name = name
this.age = age
}
// 父類成員的屬性
call(){
console.log('我是動物');
}
}
class Dog extends Animals {
// 構造方法
constructor(name,age,color,gender){
// 調用父類方法,需要用super(),super()就是父類的constructor()方法
super(name,age)
this.color = color
this.gender = gender
}
// 子類獨有的方法
say(){
console.log('汪汪汪?。。?);
}
// 當子類和父類重名時,優(yōu)先調用的是子類的方法
call(){
console.log('我也是動物');
// 如果想調用父類方法,使用如下語句:super.父類方法()
super.call()
}
}
// 實例化子類對象
const d = new Dog('小明',3,'棕色','雄')
console.log(d);
d.call()
d.say()
</script>
super 關鍵字
上面代碼用到 super 這個關鍵字,這里簡單說明一下:子類繼承父類的 constructor() 構造函數中必須要有 super(),代表調用父類的構造函數,沒有就會報錯,super雖然代表父類的構造函數,但是返回的是子類的實例,即super內部的this指的是子類的實例。作為函數時,super() 只能用在子類的構造函數中,用在其他地方就會報錯。
判斷繼承是否存在
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)屬性 屬性為數值
static age = 18
// 父類靜態(tài)屬性 屬性為對象
static h = {height:180}
// 父類靜態(tài)方法
static say(){
console.log('hello world');
}
}
// 子類繼承父類
class boy extends people {
constructor(){
// 調用父類的構造函數
super()
// boy類繼承靜態(tài)屬性時,會采用淺拷貝,拷貝父類靜態(tài)屬性的值,因此people.age和boy.age是兩個彼此獨立的屬性。
boy.age--
// 如果父類的靜態(tài)屬性的值是一個對象,那么子類的靜態(tà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 = '張三'
// 定義用來讀取私有屬性和方法的函數
getName(){
return this.#name
}
}
class boy extends people {
constructor(){
// 調用父類的構造函數
super()
console.log(this.getName());//張三
}
}
let b = new boy()
</script>class顯示原型與隱式原型關系
每個對象都有隱式原型 __proto__ 屬性,指向對應的構造函數的顯示原型 prototype 屬性,class作為構造函數的語法糖,同時也具有 prototype 屬性和 __proto__ 屬性,所以存在兩條繼承鏈。當然這里這做一個了解。
<script>
class people {}
class boy extends people{}
// 子類的__proto__屬性,表示構造函數的繼承,總是指向父類。
console.log(boy.__proto__ === people); // true
// 子類prototype屬性的__proto__屬性,表示方法的繼承,總是指向父類的prototype屬性。
console.log(boy.prototype.__proto__ === people.prototype); // true
</script>到此這篇關于JavaScript Class類實例講解的文章就介紹到這了,更多相關JS Class類內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
JavaScript基于libgif.js實現控制gif動畫幀
這篇文章主要為大家詳細介紹了JavaScript如何利用libgif.js插件控制gif動畫幀,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2024-02-02
JavaScript遍歷table表格中的某行某列并打印其值
這篇文章主要介紹了JavaScript遍歷table表格中的某行某列并打印其值,需要的朋友可以參考下2014-07-07
JavaScript和jQuery獲取input框的絕對位置實現方法
下面小編就為大家?guī)硪黄狫avaScript和jQuery獲取input框的絕對位置實現方法。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-10-10
Javascript?promise.all的用法介紹(簡潔易懂)
這篇文章主要給大家介紹了關于Javascript?promise.all用法的相關資料,Promise.all()方法是一個Promise對象方法,可以將多個Promise實例包裝成一個新的Promise對象,最終返回一個數組,需要的朋友可以參考下2023-07-07

