javascript中的類
function PersonType(name){
this.name = name;
}
PersonType.prototype.sayName = function(){
console.log(this.name)
}
var person = new PersonType("Nicholas")
person.sayName(); // outputs "Nicholas"
console.log(person instanceof PersonType) // true
console.log(person instanceof Object) // true
類聲明
class PersonClass {
// 等價於PersonType構造函數
constructor(name){
this.name = name
}
// 等價於PersonType.prototype.sayName
sayName(){
console.log(this.name)
}
}
let person = new PersonClass("Nicholas");
person.sayName(); // outputs "Nicholas"
console.log(person instanceof PersonClass) //true
console.log(person instanceof Object) // true
console.log(typeof PersonClass) // function
console.log(typeof PersonClass.prototype.sayName) // function
class是語法糖,PersonClass聲明實際上創建了一個具有構造函數方法行為的函數。通過Symbol.iterator定義生成器方法即可為定義默認迭代器
class Collection {
constructor(){
this.items = [];
}
*[Symbol.iterator](){
yield *this.items.values()
}
}
var collection = new Collection();
collection.items.push(1);
collection.items.push(2);
collection.items.push(3);
for(let x of collection){
console.log(x);
}
// 輸出:
// 1
// 2
// 3
靜態成員
ES6類語法簡化了創建靜態成員的過程,在方法或訪問器屬性名前使用正式的靜態注釋即可。
class PersonClass {
// 等價於PersonType構造函數
constructor(name){
this.name = name
}
// 等價於PersonType.prototype.sayName
sayName(){
console.log(this.name)
}
// 等價於等價於PersonType.create
static create(name){
return new PersonClass(name)
}
}
let person = PersonClass.create("Nicholas")
繼承與派生類
實現繼承與自定義類型是一個不小的工作,嚴格意義上的繼承需要多個步驟實現
function Rectangle(length,width){
this.length = length;
this.width = width;
}
Rectangle.prototype.getArea = function(){
return this.length*this.width
}
function Square(length){
Rectangle.call(this,length,length)
}
Square.prototype = Object.create(Rectangle.prototype,{
constructor:{
value:Square,
enumerable:true,
writable:true,
configurable:true
}
})
var square = new Square(3)
console.log(square.getArea()); // 9
console.log(square instanceof Square) // true
console.log(square instanceof Rectangle) // true
ES6使用extends關鍵字可以指定類繼承的函數。原型會自動調整,通過調用super()方法即可訪問基類的構造函數
class Rectangle {
constructor(length,width){
this.length = length;
this.width = width
}
getArea(){
return this.length*this.width;
}
}
class Square extends Ractangle {
constructor(length){
// Rectangle.call(this,length,length)
super(length,length)
}
}
var square = new Square(3)
console.log(square.getArea()); // 9
console.log(square instanceof Square) // true
console.log(square instanceof Rectangle) // true
繼承自其的類我們稱之為派生類,如果在派生類中指定了構造函數必須調用super(),如果不這樣做程序就會報錯。
- super
- 只可在派生類的構造函數中使用super(),非派生類不可使用
- 在構造函數中訪問this之前一定要調用super,它負責初始化this,
- 如果不想調用super(),則唯一的方法是讓類的構造函數返回一個對象。
類方法遮蔽
派生類中的訪問總會覆蓋基類中的同名方法,如果想調用基類中的方法,我們可以使用super.getArea()
class Square extends Rectangle {
constructor(length){
super(length,length)
}
//覆蓋並遮蔽Rectangle.prototype.getArea()方法
getArea(){
return this.length*this.length
}
}
派生自表達式的類
ES6最強大的一面或許是從表達式導出類的功能了。只要表達式可以被解析為一個函數並且具有[[Construct]]屬性和原型,那麼就可以用extends進行派生。
內建對象的繼承
class MyArray extends Array {
// 空
}
var colors = new MyArray();
colors[0]="red"
console.log(colors.length) // 1
colors.length = 0
console.log(colors[0]); // undefined
MyArray直接繼承自Array,其行為與Array也很相似,操作數值型屬性會更新length屬性,操作length屬性也會更新數值型屬性。於是可以正確地繼承Array對象來創建自己的派生數組類型
Symbol.species屬性
內建對象繼承的一個實用之處是,原本在內建對象中返回實例自身的方法將自動返回派生類的實現。如你有一個繼承自Array的派生類MyArray,那麼像slice()這樣的方法也會返回一個MyArray的實例
class MyArray extends Array{
// 空
}
let items = new MyArray(1,2,3,4),
subitems = items.slice(1,3);
console.log(items instanceof MyArray); //true
console.log(subitems instanceof Myarray); // true
Symbol.species是諸多內部Symbol中的一個,它被用於定義返回函數的靜態訪問器屬性。被返回的函數是一個構造函數,每當要在實例方法中(不是構造函數中)創建類的實例時必須使用這個構造函數。以下這些都是實現該屬性定義的Symbol.species
- Array
- ArrayBuffer
- Map
- Promise
- RegExp
- Set
- Typed arrays
// 幾個內建類型像這樣使用
class MyClass {
static get [Symbol.species](){
return this
}
constructor(value){
this.value = value
}
clone(){
return new this.constructor[Symbol.species](this.value)
}
}
在構造函數中使用new.target
class Shape {
constructor(){
if(new.target === Shape){
throw new Error("這個類是不能直接被實例化的")
}
}
}
class Rectangle extends Shape {
constructor(length,width){
super();
this.length = length;
this.width = width;
}
}
let x = new Shap(); // 拋出錯誤
let y = new Rectangle(3,4) // 正常執行
console.log(y instanceof Shape) //true
主題測試文章,只做測試使用。發佈者:Walker,轉轉請注明出處:https://walker-learn.xyz/archives/4335