//創(chuàng)建構(gòu)造函數(shù)User
function User(name, email) {
this.name = name;
this.email = email;
// a --- info 每次實例化都會重新生成一個,消耗內(nèi)存
this.info = function() {
console.log(`Hi I am ${this.name}`)
}
}
// b --- info 定義到原型對象
User.prototype.info = function() {
console.log(`Hi I am ${this.name}`)
}
//創(chuàng)建 兩個實例對象
const protein = new User('protein', 'i@protein.com')
const tomato = new User('tomato', 'i@tomato.com')
// b --- info 重寫原型對象的方法
User.prototype.info = function() {
console.log(`Hi I am ${this.name}, my email is ${this.email}`)
}
ES6 類 基本語法
// 聲明類 typeof 是 function 一種特殊的函數(shù) 因為沒有函數(shù)提升 必須在聲明之后才能使用
class User {
// 定義構(gòu)造函數(shù)
constructor(name, email) {
this.name = name;
this.email = email;
}
// 定義 info 方法
info() {
console.log(`Hi I am ${this.name}, my email is ${this.email}`);
}
// 定義靜態(tài)方法 只能在原型對象上調(diào)用 類似于 Array.from() 區(qū)別于 arr.push()
description() {
console.log(`this is a class`);
}
// set 關(guān)鍵字定義屬性或者方法
set github(value) {
this.githubName = value;
}
// get 對應(yīng)set
get github() {
return `https://github.com/${this.githubName}`;
}
}
// 創(chuàng)建 兩個實例對象
const protein = new User('protein', 'i@protein.com')
const tomato = new User('tomato', 'i@tomato.com')
// 使用 set get
protein.github = 'shadow-fiend'; // "shadow-fiend"
protein.github // "https://github.com/shadow-fiend"
首先用 class 定義了一個“類”,可以看到里面有一個 constructor 方法,這就是構(gòu)造方法,而 this 關(guān)鍵字則代表實例對象。簡單地說,constructor 內(nèi)定義的方法和屬性是實例對象自己的,而 constructor 外定義的方法和屬性則是所有實力對象可以共享的。
類的繼承
Class Animal {
constructor(name) {
this.name = name;
this.belly = [];
}
eat(food) {
this.belly.push(food);
}
speak() {
console.log(`Hi I am ${this.name}`);
}
}
// ES5 實現(xiàn)繼承 ES5 -->
function Dog() { // ES5 --> 創(chuàng)建 Dog 構(gòu)造函數(shù)
Animal.call(this, name, age); // ES5 --> 調(diào)用積類構(gòu)造函數(shù)
this.name = name;
this.age = age;
}
Dog.prototype = new Animal(); // ES5 --> Dog 原型對象指向 Animal 對象的實例 原型對象的 constructor 會發(fā)生改變
Dog.prototype.constructor = Dog; // ES5 --> 原型對象的 constructor 在給它指回去
// ES6 實現(xiàn)繼承
Class Dog extends Animal {
constructor(name, age) {
super(name); // 否則在后面獲取不到 this 值
}
bark() {
console.log(`bark bark!`);
}
speak() { // 子類可以重寫父類的方法
console.log(`bark bark Hi I am ${this.name}`);
}
}
const Protein = new Dog('protein', 2);
Class 之間可以通過 extends 關(guān)鍵字實現(xiàn)繼承,這比 ES5 的通過修改原型鏈實現(xiàn)繼承,要清晰和方便很多。上面定義了一個 Dog 類,該類通過 extends 關(guān)鍵字,繼承了Animal 類的所有屬性和方法。
super 關(guān)鍵字,它指代父類的實例 ( 即父類的 this 對象 ) 。子類必須在 constructor方法中調(diào)用 super 方法,否則新建實例時會報錯。這是因為子類沒有自己的 this 對象,而是繼承父類的 this 對象,然后對其進行加工。如果不調(diào)用 super 方法,子類就得不到 this 對象。
ES6 的繼承機制,實質(zhì)是先創(chuàng)造父類的實例對象 this ( 所以必須先調(diào)用super方法 ) ,然后再用子類的構(gòu)造函數(shù)修改 this 。
ES6 類 擴展內(nèi)建對象數(shù)組
Class movieCollection extends Array {
constructor(name, ...items) {
super(...items);
this.name = name
}
add(movie) {
this.push(movie);
}
topRated(limit = 3) {
return this.sort((a, b) => (a.scores >= b.scores) ? -1 : 1).slice(0, limit);
}
}
const movies = new movieCollection('favorite movies',
{ name: 'The Croods', scores: 8.7 },
{ name: 'The ShawThank Redemption', scores: 9.6 },
{ name: 'Leon', scores: 9.4 },
{ name: 'Days of Summer', scores: 8.0 }
)
movies.push({ name: 'Pride & Prejudice', score: 8.4 })
console.table(movies.topRated());
// 可以用 for of 來循環(huán)除 name 之外的數(shù)組的屬性
for(let movie of movies) {console.log(movie)}