在ES5聲明一個函數(能夠new),再將方法添加到這個方法的原型上,來建立自定義類型。javascript
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function() {
console.log(this.name);
};
let person = new Person("xunuo0x");
person.sayName(); // 輸出 "xunuo0x"
console.log(person instanceof Person); // true
console.log(person instanceof Object); // true
複製代碼
本質:ES5實現方式的語法糖java
咱們拿下面用class
聲明的Person
爲例:也就是說Person
類爲一個具備構造函數行爲的函數,其中內部方法sayName
實際上就是Person.prototype.sayName()
。因此說本質上是ES5實現方式的語法糖。函數
console.log(typeof Person) // 'function'
複製代碼
區別在於,類的屬性不可從新賦值和不可枚舉的,Person.prototype
就是一個只讀屬性。性能
聲明:ui
class Person {
// 等價於 Person 構造器
constructor(name) {
this.name = name;
}
// 更加簡單的聲明類的內部函數
// 等價於 Person.prototype.sayName
sayName() {
console.log(this.name);
}
}
let person = new Person("xunuo0x");
person.sayName(); // 輸出 "xunuo0x"
console.log(person instanceof Person); // true
console.log(person instanceof Object); // true
console.log(typeof Person); // "function"
console.log(typeof Person.prototype.sayName); // "function"
複製代碼
用ES5重寫以下: 在實現的時候,主要使用Object.defineProperty()
實現class內部函數this
// 直接等價於 Person
let Person2 = (function() {
"use strict";
// 有個同名的只讀內部函數
// **類的內部不能修改類名**
const Person2 = function(name) {
// 確認函數被調用時使用了 new
if (typeof new.target === "undefined") {
throw new Error("Constructor must be called with new.");
}
this.name = name;
}
Object.defineProperty(Person2.prototype, "sayName", {
value: function() {
// 確認函數被調用時沒有使用 new
if (typeof new.target !== "undefined") {
throw new Error("Method cannot be called with new.");
}
console.log(this.name);
},
// **類的內部方法定義爲不可枚舉**
enumerable: false,
writable: true,
configurable: true
});
return Person2;
}());
複製代碼
let Person = class{...}
let Person = PersonClass class{...}
const PersonClass
做爲內部實現的類名js中能看成值來使用的稱爲一級公民spa
用法:prototype
// 類名做爲參數傳入函數
function crateObj (ClassName){
return new ClassName()
}
// 當即執行,實現單例模式
let person = new class {
constructor (name) {
this.name = name
}
say () {
console.log(this.name)
}
}('xunuo0x')
person.say() // "xunuo0x"
複製代碼
Object.defineProperty()
定義Person.create() = function() {}
只要一個表達式能返回具備
[[constructor]]
就可使用extends
繼承;也就是說能夠繼承一個函數code
ES5中的繼承對象
function Parent (name) {
this.name = name
}
Parent.prototype.sayName = function () {
console.log(this.name)
}
function Child (name) {
Parent.call(this, name)
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
複製代碼
在ES6中的繼承
class Parent (name) {
constructor (name) {
this.name = name
}
sayName() {
console.log(this.name)
}
}
class Child extends Parent (name) {
constructor(name) {
super(name)
}
// 重寫父類中的方法
sayName () {
console.log(`Child ${this.name}`)
}
}
複製代碼
Symbol.species
屬性Symbol.species
class MyClass extends Array {
static get [Symbol.species]() {
return this; // 默認返回MyClass類型
return Array; // 修改返回基類
}
constructor(value) {
this.value = value;
}
}
複製代碼
constructor()
中new.target
不多是undefinedfunction mixin (...mixin) {
var base = function() {}
Object.assign(base, ...mixin)
return mixin
}
class Person extends mixin(Animal, Monkey) {
constructor(){
super(Animal, Monkey)
// ......
}
}
複製代碼
class
簡化了ES5中的繼承,可是未改變現有的繼承模型。能夠理解爲是ES5基於原型鏈的語法糖class
聲明一個類,constructor()
做爲構造函數,屬性在constructor()
中初始化class
內能夠定義getter/setter
訪問器屬性class
內定義非靜態方法,靜態方法綁定在構造器上class
必需要new
關鍵字extends
實現繼承,子類中調用super()
訪問父類構造函數extends
可能還會下降性能