詳解ES6中的class——基本概念

歡迎關注前端小謳的github,閱讀更多原創技術文章javascript

用構造函數,生成對象實例:前端

  1. 使用構造函數,而且new 構造函數(), 後臺會隱式執行new Object() 建立對象
  2. 將構造函數的做用域給新對象,(即new Object() 建立出的對象),函數體內的this表明new Object() 出來的對象
  3. 執行構造函數的代碼
  4. 返回新對象( 後臺直接返回)
function Person1(name, age) {
  this.name = name
  this.age = age
}
Person1.prototype.say = function () {
  return "My name is " + this.name + ", I'm " + this.age + " years old."
}
var obj = new Person1("Simon", 28);
console.log(obj.say()); // My name is Simon, I'm 28 years old.

用class改寫上述代碼:java

  1. 經過class關鍵字定義類,使得在對象寫法上更清晰,讓javascript更像一種面向對象的語言
  2. 在類中聲明方法的時,不可給方法加function關鍵字
class Person2 {
  // 用constructor構造方法接收參數
  constructor(name, age) {
    this.name = name; // this表明的是實例對象
    this.age = age;
  }
  // 類的方法,此處不能加function
  say() {
    return "My name is " + this.name + ", I'm " + this.age + " years old."
  }
}
var obj = new Person2("Coco", 26);
console.log(obj.say()); // My name is Coco, I'm 26 years old.
  1. ES6中的類,實質上就是一個函數
  2. 類自身指向的就是構造函數
  3. 類其實就是構造函數的另一種寫法
console.log(typeof Person2); // function
console.log(Person1 === Person1.prototype.constructor); // true
console.log(Person2 === Person2.prototype.constructor); // true
構造函數的prototype屬性,在ES6的class中依然存在:
// 構造1個與類同名的方法 -> 成功實現覆蓋
Person2.prototype.say = function () {
  return "證實一下:My name is " + this.name + ", I'm " + this.age + " years old."
}
var obj = new Person2("Coco", 26);
console.log(obj.say()); // 證實一下:My name is Coco, I'm 26 years old.

// 經過prototype屬性對類添加方法
Person2.prototype.addFn = function () {
  return "經過prototype新增長的方法addFn"
}
var obj = new Person2("Coco", 26);
console.log(obj.addFn()); // 經過prototype新增長的方法addFn
經過Object.assign方法來爲對象動態增長方法:
Object.assign(Person2.prototype, {
  getName: function () {
    return this.name;
  },
  getAge: function () {
    return this.age;
  }
})
var obj = new Person2("Coco", 26);
console.log(obj.getName()); // Coco
console.log(obj.getAge()); // 26
constructor方法是類的構造函數的默認方法
new生成對象實例時,自動調用該方法
class Box {
  constructor() {
    console.log("自動調用constructor方法"); // 實例化對象時,該行代碼自動執行
  }
}
var obj = new Box();

若沒有定義constructor方法,將隱式生成一個constructor方法:git

  1. 即便沒有添加構造函數,構造函數也是存在的
  2. constructor方法默認返回實例對象this
  3. 能夠指定constructor方法返回一個全新的對象,讓返回的實例對象不是該類的實例對象
class Text1 {
  constructor() {
    this.text = "這是一段Text";
  }
}
class Text2 {
  constructor() {
    return new Text1(); // 返回一個全新的對象
  }
}
var obj = new Text2()
console.log(obj.text); // 這是一段Text

實例屬性:constructor中定義的屬性,即定義在this對象上
原型屬性:constructor外聲明的屬性,即定義在class上github

  1. hasOwnProperty() 函數,判斷屬性是否爲實例屬性 -> true or false
  2. in操做符, 判斷對象可否訪問給定屬性 -> true or false(與該屬性存在於實例/原型中無關)
class Text3 {
  // 實例屬性,定義在this對象上
  constructor(text1, text2) {
    this.text1 = text1
    this.text2 = text2
  }
  // 原型屬性,定義在class上
  text3() {
    return text1 + text2
  }
}
var obj = new Text3('123', '234')
console.log(obj.hasOwnProperty("text1")); // true
console.log(obj.hasOwnProperty("text2")); // true
console.log(obj.hasOwnProperty("text3")); // false
console.log("text1" in obj); // true
console.log("text2" in obj); // true
console.log("text3" in obj); // true
console.log("text4" in obj); // false
類的全部實例共享一個原型對象, 它們的原型都是Person.prototype, 因此proto屬性是相等的
class Text4 {
  constructor(text1, text2) {
    this.text1 = text1;
    this.text2 = text2;
  }
  text3() {
    return text1 + text1;
  }
}
// text1與text2都是Text4的實例 -> 它們的__proto__都指向Text4的prototype
var text1 = new Text4('1234', '5678');
var text2 = new Text4('4321', '8765');
console.log(text1.__proto__ === text2.__proto__); // true

經過proto來爲類增長方法:函數

  1. 使用實例的proto屬性改寫原型
  2. 會改變Class的原始定義,影響到全部實例,不推薦使用
class Num {
  constructor(num1, num2) {
    this.num1 = num1;
    this.num2 = num2;
  }
  sum() {
    return num1 + num2;
  }
}
var num1 = new Num(20, 78);
var num2 = new Num(40, 96);
num1.__proto__.minus = function () {
  return this.num2 - this.num1;
}
console.log(num1.minus()); // 76 -> 改變了class的原始定義,爲class新增原型屬性minus
console.log(num2.minus()); // 20 -> num2和num1共享原型對象Num,能夠調用原型對象的minus方法

class不存在變量提高,必須先定義再使用:this

  1. ES6不會把class的聲明提高到代碼頭部2
  2. ES5存在變量提高, 能夠先使用再定義
//ES5能夠先使用再定義,存在變量提高
new A()
function A() {}

//ES6不能先使用再定義,不存在變量提高(報錯)
new B() // B is not defined
class B {}
相關文章
相關標籤/搜索