1.使用class定義一個(gè)類:類的聲明
和類的表達(dá)式
//方法一:類的聲明
class Person {
}
//方法二:類的表達(dá)式
const Student = class {
}
console.log(Person.prototype) //{}
console.log(Object.getOwnPropertyDescriptors(Person.prototype))
// {
// constructor: {
// value: [class Person],
// writable: true,
// enumerable: false,
// configurable: true
// }
// }
console.log(Person.prototype.__proto__)//[Object:null prototype] {}
console.log(Person.prototype.constructor) //[class Person]
console.log(typeof Person) //function
var p = new Person()
console.log(p.__proto__ === Person.prototype) //true
2.類的構(gòu)造函數(shù)
當(dāng)使用new 調(diào)用Person類創(chuàng)建一個(gè)對象時(shí)砚蓬,傳遞的參數(shù)如果傳遞給類?
class Person {
}
var p = new Person('小名', 30)
var s = new Person('小紅', 20)
通過new調(diào)用類傳遞的參數(shù)
旦袋,會作為參數(shù)
傳遞給類的構(gòu)造函數(shù)
定義類的時(shí)候,
如果沒有明確定義類的構(gòu)造方法,會使用類的默認(rèn)的構(gòu)造方法
如果明確定義了構(gòu)造方法酗宋,就使用定義的構(gòu)造方法
一個(gè)類只有一個(gè)構(gòu)造方法
// 定義類的時(shí)候,
// 如果沒有明確定義類的構(gòu)造方法疆拘,會使用類的默認(rèn)的構(gòu)造方法
// 如果明確定義了構(gòu)造方法蜕猫,就使用定義的構(gòu)造方法
// 一個(gè)類只有一個(gè)構(gòu)造方法
class Student {}
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
console.log(Student.constructor); // [Function: Function] 輸出類的默認(rèn)構(gòu)造方法
console.log(Person.constructor); // [Function: Function]
var p = new Person("小名", 30);
var s = new Person("小紅", 20);
console.log(p.name, p.age); //小名 30
console.log(s.name, s.age); //小紅 20
當(dāng)使用new 調(diào)用類時(shí),會執(zhí)行類的構(gòu)造函數(shù)哎迄,
調(diào)用類時(shí)傳遞的參數(shù)回右,會作為參數(shù)傳給類的構(gòu)造函數(shù)
class Person {
//constructor為類的構(gòu)造函數(shù)(構(gòu)造方法)
//類的構(gòu)造函數(shù)被調(diào)用時(shí):
//1.在內(nèi)存中創(chuàng)建一個(gè)新對象(空對象)var moni = {}
//2.這個(gè)對象內(nèi)部的[[prototype]]原型對象會指向類的prototype原型對象 moni.__proto__ = Person.prototype
//3.this指向這個(gè)對象 this = moni
//4.執(zhí)行構(gòu)造函數(shù)內(nèi)部的代碼
//5.如果構(gòu)造函數(shù)沒有返回非空對象隆圆,則返回創(chuàng)建出來的新對象 return moni
constructor(name, age) {
this.name = name
this.age = age
}
}
//當(dāng)使用new 調(diào)用類時(shí),會執(zhí)行類的構(gòu)造函數(shù)翔烁,
//調(diào)用類時(shí)傳遞的參數(shù)渺氧,會作為參數(shù)傳給類的構(gòu)造函數(shù)
var p = new Person('小名', 30)
var s = new Person('小紅', 20)
3.給類的prototype原型對象上添加方法
class Person {
constructor(name, age) {
//定義的屬性定義在類的實(shí)例上
this.name = name;
this.age = age;
}
//在類的prototype原型對象上添加方法,不可枚舉
eatting() {
console.log(this.name + " is eatting");
}
}
var p = new Person("xiaoming", 30);
p.eatting(); //xiaoming is eatting
console.log(p); //Person { name: 'xiaoming', age: 30 }
console.log(Person.prototype); //{} 定義類時(shí),添加到類的prototype原型對象上的方法是不可枚舉的
console.log(Object.getOwnPropertyDescriptors(Person.prototype));
// {
// constructor: {
// value: [class Person],
// writable: true,
// enumerable: false,
// configurable: true
// },
// eatting: {
// value: [Function: eatting],
// writable: true,
// enumerable: false,
// configurable: true
// }
// }
相當(dāng)于下面:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.eatting = function () {
console.log(this.name + " is eatting");
}
4.給類的prototype原型對象上添加訪問器方法
class Person {
constructor(name, age) {
//定義的屬性定義在類的實(shí)例上
this.name = name;
this._age = age;
}
//在類的prototype原型對象上添加方法,不可枚舉,被類的實(shí)例調(diào)用
eatting() {
console.log(this.name + " is eatting");
}
//在類的prototype原型對象上定義訪問器方法,不可枚舉,被類的實(shí)例調(diào)用
get age() {
return this.age;
}
set age(newVal) {
this._age = newVal
}
}
var p = new Person('xiaoming', 30)
p.eatting() //xiaoming is eatting
console.log(p) //Person { name: 'xiaoming', _age: 30 }
console.log(Person.prototype) // {}
console.log(Object.getOwnPropertyDescriptors(Person.prototype))
// {
// constructor: {
// value: [class Person],
// writable: true,
// enumerable: false,
// configurable: true
// },
// eatting: {
// value: [Function: eatting],
// writable: true,
// enumerable: false,
// configurable: true
// },
// age: {
// get: [Function: get age],
// set: [Function: set age],
// enumerable: false,
// configurable: true
// }
// }
5.class類中定義靜態(tài)方法
class Person {
constructor(name, age) {
//定義的屬性定義在類的實(shí)例上
this.name = name;
this.age = age;
}
//在類的prototype原型對象上添加方法,不可枚舉,被類的實(shí)例調(diào)用
eatting() {
console.log(this.name + " is eatting");
}
//在類上添加靜態(tài)方法蹬屹,不可枚舉侣背,被類本身調(diào)用
static createPerson() {
return new Person("甲", 30);
}
}
var p = new Person("xiaoming", 30);
p.eatting(); //xiaoming is eatting
console.log(p); //Person { name: 'xiaoming', age: 30 }
console.log(Object.getOwnPropertyDescriptors(Person.prototype));
// {
// constructor: {
// value: [class Person],
// writable: true,
// enumerable: false,
// configurable: true
// },
// eatting: {
// value: [Function: eatting],
// writable: true,
// enumerable: false,
// configurable: true
// },
// }
console.log(Person); //[class Person]
console.log(Object.getOwnPropertyDescriptors(Person));
// {
// length: { value: 2, writable: false, enumerable: false, configurable: true },
// prototype: {
// value: {},
// writable: false,
// enumerable: false,
// configurable: false
// },
// createPerson: {
// value: [Function: createPerson],
// writable: true,
// enumerable: false,
// configurable: true
// },
// name: {
// value: 'Person',
// writable: false,
// enumerable: false,
// configurable: true
// }
// }
console.log(Person.createPerson()); //Person { name: '甲', age: 30 }
相當(dāng)于
function Person (name, age){
this.name = name;
this.age = age;
}
Person.prototype.eatting = function () {
console.log(this.name + " is eatting");
}
Person.createPerson = function () {
return new Person("甲", 30);
}
6.class類中的繼承
子類如果實(shí)現(xiàn)了繼承,在子類構(gòu)造函數(shù)中訪問this或return之前必須通過super調(diào)用父類構(gòu)造函數(shù)
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
//子類如果實(shí)現(xiàn)了繼承慨默,在子類構(gòu)造函數(shù)中訪問this或return之前必須通過super調(diào)用父類構(gòu)造函數(shù)
class Student extends Person {
constructor(name, age, address) {
super(name, age);
this.address = address;
}
}
var stu = new Student('小名', 30, '北京')
console.log(stu) //Student { name: '小名', age: 30, address: '北京' }
console.log(stu.__proto__)//Person {} 輸出結(jié)果為一個(gè)對象贩耐,屬于Person類
//因?yàn)閟tu.__proto__為Student.prototype,
//而Student.prototype為一個(gè)對象,此對象的__proto__原型對象為Person.prototype
//所以Student.prototype為Person類的一個(gè)實(shí)例對象厦取,即stu.__proto__為一個(gè)Person類的一個(gè)實(shí)例對象
//stu的[[prototype]]原型對象為Person的實(shí)例潮太,為[[prototype]]原型對象為Person.prototype原型對象的對象
console.log(stu.__proto__.__proto__ === Person.prototype) //true
子類繼承父類的原型對象上的方法和子類繼承父類上的靜態(tài)屬性和方法
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
running() {
console.log(this.name + " is running");
}
static createPerson() {
console.log("創(chuàng)建person");
}
}
//子類如果實(shí)現(xiàn)了繼承,在子類構(gòu)造函數(shù)中訪問this或return之前必須通過super調(diào)用父類構(gòu)造函數(shù)
class Student extends Person {
constructor(name, age, address) {
super(name, age);
this.address = address;
}
//在子類的原型對象上定義running方法
eatting() {
console.log(this.name + " is eatting");
}
//在子類上定義靜態(tài)方法
static createStudent() {
console.log("創(chuàng)建student");
}
}
var stu = new Student("小名", 30, "北京");
console.log(stu); //Student { name: '小名', age: 30, address: '北京' }
stu.running(); //小名 is running
stu.eatting(); //小名 is eatting
Student.createStudent(); //創(chuàng)建student
Student.createPerson(); //創(chuàng)建person
console.log(stu.__proto__); //Person {} 為一個(gè)Person類的對象虾攻,即類Person的一個(gè)實(shí)例
console.log(Object.getOwnPropertyDescriptors(stu.__proto__));
// {
// constructor: {
// value: [class Student extends Person],
// writable: true,
// enumerable: false,
// configurable: true
// },
// eatting: {
// value: [Function: eatting],
// writable: true,
// enumerable: false,
// configurable: true
// }
// }
//定義子類時(shí)铡买,定義在子類prototype原型對象的方法,在子類的prototype對象上
console.log(stu.__proto__.__proto__); //{} 為父類Person類的prototype原型對象
console.log(stu.__proto__.__proto__ === Person.prototype); //true
console.log(Object.getOwnPropertyDescriptors(stu.__proto__.__proto__));
// {
// constructor: {
// value: [class Person],
// writable: true,
// enumerable: false,
// configurable: true
// },
// running: {
// value: [Function: running],
// writable: true,
// enumerable: false,
// configurable: true
// }
// }
// 定義子類時(shí)台谢,繼承的父類的prototype原型對象上的方法寻狂,依然在父類的prototype原型對象上
console.log(Student) //[class Student extends Person]
console.log(Object.getOwnPropertyDescriptors(Student))
// {
// length: { value: 3, writable: false, enumerable: false, configurable: true },
// prototype: {
// value: Person {},
// writable: false,
// enumerable: false,
// configurable: false
// },
// createStudent: {
// value: [Function: createStudent],
// writable: true,
// enumerable: false,
// configurable: true
// },
// name: {
// value: 'Student',
// writable: false,
// enumerable: false,
// configurable: true
// }
// }
console.log(Student.__proto__ === Person) //true
// 因?yàn)樽宇惖腫[prototype]]原型對象為父類Person,所以可以通過子類Student調(diào)用父類Person上的方法
類對父類方法的重寫
在子類定義prototype原型對象方法內(nèi)部,可以通過super調(diào)用父類的prototype對象朋沮,父類prototype對象上的方法內(nèi)部的this被綁定為子類prototype原型對象方法內(nèi)部的this
在子類定義靜態(tài)方法內(nèi)部蛇券,可以通過super調(diào)用父類
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
running() {
console.log(this.name + ' is running')
}
eatting() {
console.log(this.name + ' is eatting')
}
static createPerson() {
console.log('第一步')
}
}
//子類如果實(shí)現(xiàn)了繼承,在子類構(gòu)造函數(shù)中訪問this或return之前必須通過super調(diào)用父類構(gòu)造函數(shù)
class Student extends Person {
constructor(name, age, address) {
super(name, age);
this.address = address;
}
//子類對父類方法的重寫
eatting() {
console.log('今天吃的很飽')
}
//在子類的原型對象上定義running方法
running() {
//通過super調(diào)用父類的原型對象樊拓,從父類的原型對象上獲取running方法纠亚,
//此方法執(zhí)行時(shí)。方法內(nèi)容的this被綁定為當(dāng)前作用域的this
super.running()
console.log(this.name + ' run fastest')
}
//在子類上定義靜態(tài)方法
static createPerson() {
//通過super獲取父類筋夏,調(diào)用父類上的靜態(tài)方法
super.createPerson()
console.log('第二步')
}
}
var stu = new Student('小名', 30, '北京')
console.log(stu) //Student { name: '小名', age: 30, address: '北京' }
stu.running()
//小名 is running
//小名 run fastest
Student.createPerson()
// 第一步
// 第二步