ES6中的class在ES5中的實現

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

類的由來

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類的構造方法。babel

ES6的類能夠看做構造函數的另外一種寫法。

class Person {
  // ...
}

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

上面代碼代表,類的數據類型就是函數,類自己就指向構造函數。函數

ES6的類在es5中的實現原理

es6中的class的具體使用能夠參考阮一峯Class 的基本語法this

咱們如今看下es6中的class是怎麼經過es5語法實現的,讓我藉助babel來一步一步看一下class轉換成es5的代碼es5

先添加一個類prototype

// 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也能夠執行。code


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

// 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;
}();
相關文章
相關標籤/搜索