關於js中function和class的內在關系及區別的理解


在js中,從es6開始引進class,根本上是基於js中已經存在的原型繼承的語法糖,class語法並沒有引進一種新的面向對象的繼承機制。

一、定義class

  class事實上是一種特殊的funcion,就像可以定義funcion表達式和funcion聲明一樣,class語法也有2種形式:class表達式和class聲明。

  1、class聲明

  定義一個class,可以使用class關鍵字加上類名。需要注意的是,funcion聲明和class聲明有一個重要的卻別:funcion聲明是hosting(狀態提升)的,而class不是,class需要先聲明再使用。

1 class Rectangle {
2   constructor(height, width) {
3     this.height = height;
4     this.width = width;
5   }
6 }

  2、class表達式

  class表達式類名可選,已經命名的class可以通過實例的'.name'屬性獲取,依據class自身的命名。

 1 // unnamed
 2 let Rectangle = class {
 3   constructor(height, width) {
 4     this.height = height;
 5     this.width = width;
 6   }
 7 };
 8 console.log(Rectangle.name);
 9 // output: "Rectangle"
10 
11 // named
12 let Rectangle = class Rectangle2 {
13   constructor(height, width) {
14     this.height = height;
15     this.width = width;
16   }
17 };
18 console.log(Rectangle.name);
19 // output: "Rectangle2"

 

二、class中body和method的定義

  class的body部分包含在花括號{}中,這里是定義class成員的地方,比如constructor和method。

  1、constructor

  constructor方法是一個特殊的方法,用來創建並初始化一個對象。在一個class中只能有一個命名為constructor的特殊方法,如果包含多個將會報錯。

  constructor中可以通過super關鍵字,調用父類的constructor方法。

  2、prototype methods(原型方法)

 1 class Rectangle {
 2   constructor(height, width) {
 3     this.height = height;
 4     this.width = width;
 5   }
 6   // Getter
 7   get area() {
 8     return this.calcArea();
 9   }
10   // Method
11   calcArea() {
12     return this.height * this.width;
13   }
14 }
15 
16 const square = new Rectangle(10, 10);
17 
18 console.log(square.area); // 100

  3、static methods(靜態方法)

  通過static關鍵字為一個class創建靜態方法,static methods的調用無需對class實例化,也不能被實例對象所調用。

 1 class Point {
 2   constructor(x, y) {
 3     this.x = x;
 4     this.y = y;
 5   }
 6     
 7   static distance(a, b) {
 8     const dx = a.x - b.x;
 9     const dy = a.y - b.y;
10 
11     return Math.hypot(dx, dy);
12   }
13 }
14 
15 const p1 = new Point(5, 5);
16 const p2 = new Point(10, 10);
17 
18 console.log(Point.distance(p1, p2)); // 7.0710678118654755

  4、static和prototype method的封裝

  當static或prototype method被調用的時候,如果沒有對this賦值,那么this將是undefine狀態。這和是否采用static模式無關,因為class類體中的代碼已經默認執行static模式。

 1 class Animal { 
 2   speak() {
 3     return this;
 4   }
 5   static eat() {
 6     return this;
 7   }
 8 }
 9 
10 let obj = new Animal();
11 obj.speak(); // Animal {}
12 let speak = obj.speak;
13 speak(); // undefined
14 
15 Animal.eat() // class Animal
16 let eat = Animal.eat;
17 eat(); // undefined

  如果以上代碼是基於傳統的function的語法,則this值是global object。

三、extends創建子類

  extends關鍵字用於在class聲明或表達式中,創建另一個class的子類。

 1 class Animal { 
 2   constructor(name) {
 3     this.name = name;
 4   }
 5   
 6   speak() {
 7     console.log(this.name + ' makes a noise.');
 8   }
 9 }
10 
11 class Dog extends Animal {
12   constructor(name) {
13     super(name); // call the super class constructor and pass in the name parameter
14   }
15 
16   speak() {
17     console.log(this.name + ' barks.');
18   }
19 }
20 
21 let d = new Dog('Mitzie');
22 d.speak(); // Mitzie barks.

  如果在子類中有constructor方法,在使用"this"之前需要調用super()。也可以繼承自function-based的class。

 1 function Animal (name) {
 2   this.name = name;  
 3 }
 4 
 5 Animal.prototype.speak = function () {
 6   console.log(this.name + ' makes a noise.');
 7 }
 8 
 9 class Dog extends Animal {
10   speak() {
11     console.log(this.name + ' barks.');
12   }
13 }
14 
15 let d = new Dog('Mitzie');
16 d.speak(); // Mitzie barks.

  需要注意的是:class不能繼承自常規對象(non-constructible),如果想繼承自常規對象,可以使用Object.setPrototypeOf()替代。

 1 const Animal = {
 2   speak() {
 3     console.log(this.name + ' makes a noise.');
 4   }
 5 };
 6 
 7 class Dog {
 8   constructor(name) {
 9     this.name = name;
10   }
11 }
12 
13 // If you do not do this you will get a TypeError when you invoke speak
14 Object.setPrototypeOf(Dog.prototype, Animal);
15 
16 let d = new Dog('Mitzie');
17 d.speak(); // Mitzie makes a noise.

四、super關鍵字調用父類

  關鍵字super用於調用父類相應的方法,這是相較於原型繼承的一個好處。

 1 class Cat { 
 2   constructor(name) {
 3     this.name = name;
 4   }
 5   
 6   speak() {
 7     console.log(`${this.name} makes a noise.`);
 8   }
 9 }
10 
11 class Lion extends Cat {
12   speak() {
13     super.speak();
14     console.log(`${this.name} roars.`);
15   }
16 }
17 
18 let l = new Lion('Fuzzy');
19 l.speak(); 
20 // Fuzzy makes a noise.
21 // Fuzzy roars.

  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM