ES6中的class在ES5中的實現


參考文章:阮一峰 Class 的基本語法

類的由來

JavaScript語言的傳統方法是通過構造函數定義並生成新對象,這種寫法和傳統的面向對象語言差異較大。所以,ES6引入了Class這個概念作為對象的模板。
class可以看作只是一個語法糖,它的絕大部分功能,ES5 都可以做到。

// es5 中的構造函數
function Person(name, age) {
    this.name = name;
    this.age = age;
}

Person.prototype.toString = function () {
    return '(' + this.name + ',' + this.age + ')';
}
var p = new Person('xiaoMing', 18);


// es6 通過class實現
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    toString() {
        return '(' + this.name + ',' + this.age + ')';
    }
}
var p = new Person('xiaoMing', 18);

上面代碼定義了一個“類”,可以看到里面有一個constructor方法,這就是構造方法,而this關鍵字則代表實例對象。也就是說,ES5 的構造函數Point,對應 ES6 的Point類的構造方法。

ES6的類可以看作構造函數的另一種寫法。

class Person {
  // ...
}

typeof Person // "function"
Person === Person.prototype.constructor // true

上面代碼表明,類的數據類型就是函數,類本身就指向構造函數。

ES6的類在es5中的實現原理

es6中的class的具體使用可以參考阮一峰Class 的基本語法

我們現在看下es6中的class是怎么通過es5語法實現的,讓我借助babel來一步一步看一下class轉換成es5的代碼

先添加一個類

// es6
class Person {
}

// 通過babel轉換成的es5語法
"use strict";


// 判斷某對象是否為某構造器的實例
function _instanceof(left, right) { 
    if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
        return !!right[Symbol.hasInstance](left); } else { return left instanceof right; }
    }
// 檢查聲明的class類是否通過new的方式調用,否則會報錯
function _classCallCheck(instance, Constructor) { if (!_instanceof(instance, Constructor)) { 
    throw new TypeError("Cannot call a class as a function"); } 
}

var Person = function Person() {
   _classCallCheck(this, Person);
};

類必須使用new調用,否則會報錯。這是它跟普通構造函數的一個主要區別,后者不用new也可以執行。


添加屬性和方法(包括靜態方法)

// es6
class Person {
  	constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    eat() {
        return  'eat'
    }
    static say() {
    	return 'say'
    }
}

// 通過babel轉換成的es5語法
"use strict";
// 判斷某對象是否為某構造器的實例
function _instanceof(left, right) { 
    if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
        return !!right[Symbol.hasInstance](left); } else { return left instanceof right; }
}

// 檢查聲明的class類是否通過new的方式調用,否則會報錯
function _classCallCheck(instance, Constructor) { if (!_instanceof(instance, Constructor)) { 
    throw new TypeError("Cannot call a class as a function"); } 
}
/**
 *將方法添加到原型上,如果是靜態方法添加到構造函數上,
 **/ 

function _defineProperties(target, props) { 
    // 遍歷函數數組,分別聲明其描述符 並添加到對應的對象上
    for (var i = 0; i < props.length; i++) { 
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false; // 設置該屬性是否能夠出現在對象的枚舉屬性中。默認為 false
        descriptor.configurable = true; // 設置該屬性描述符能夠被改變,同時該屬性也能從對應的對象上被刪除。
        if ("value" in descriptor) descriptor.writable = true; // 如果屬性中存在value, value設置為可以改變。
        Object.defineProperty(target, descriptor.key, descriptor); // 寫入對應的對象上
    }
}

// 收集公有函數和靜態方法,將方法添加到構造函數或構造函數的原型中,並返回構造函數。
function _createClass(Constructor, protoProps, staticProps) { 
    if (protoProps) _defineProperties(Constructor.prototype, protoProps); // 共有方法寫在property原型上
    if (staticProps) _defineProperties(Constructor, staticProps); // 靜態方法寫到構造函數上 
    return Constructor; 
}

var Person = function () {
    function Person(name, age) {
        _classCallCheck(this, Person);

        this.name = name;
        this.age = age;
    }

    _createClass(Person, [{
        key: "eat",
        value: function eat() {
            return 'eat';
        }
    }], [{
        key: "say",
        value: function say() {
            return 'say';
        }
    }]);

    return Person;
}();


免責聲明!

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



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