IT干货网

ES6中的class在ES5中的实现

xmjava 2022年03月15日 编程设计 169 0

参考文章:阮一峰 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; 
}(); 

评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

扁平化数据解构转化成树形结构