美文网首页
为什么ES5无法继承原生构造函数?

为什么ES5无法继承原生构造函数?

作者: 不看盛景不叙深情 | 来源:发表于2018-11-01 17:38 被阅读0次

    原生构造函数是指语言内置的构造函数,通常用来生成数据结构。ECMAScript 的原生构造函数大致有下面这些。

    Boolean()
    Number()
    String()
    Array()
    Date()
    Function()
    RegExp()
    Error()
    Object()
    

    ES5 是先新建子类的实例对象this,再将父类的属性添加到子类上,由于父类的内部属性无法获取,导致无法继承原生的构造函数。比如,Array构造函数有一个内部属性[[DefineOwnProperty]],用来定义新属性时,更新length属性,这个内部属性无法在子类获取,导致子类的length属性行为不正常。

    下面的例子中,我们想让一个普通对象继承Error对象。

    var e = {};
    
    Object.getOwnPropertyNames(Error.call(e))
    // [ 'stack' ]
    
    Object.getOwnPropertyNames(e)
    // []
    

    上面代码中,我们想通过Error.call(e)这种写法,让普通对象e具有Error对象的实例属性。但是,Error.call()完全忽略传入的第一个参数,而是返回一个新对象,e本身没有任何变化。这证明了Error.call(e)这种写法,无法继承原生构造函数。

    ES6 允许继承原生构造函数定义子类,因为 ES6 是先新建父类的实例对象this,然后再用子类的构造函数修饰this,使得父类的所有行为都可以继承。下面是一个继承Array的例子。

    class MyArray extends Array {
      constructor(...args) {
        super(...args);
      }
    }
    
    var arr = new MyArray();
    arr[0] = 12;
    arr.length // 1
    
    arr.length = 0;
    arr[0] // undefined
    

    上面代码定义了一个MyArray类,继承了Array构造函数,因此就可以从MyArray生成数组的实例。这意味着,ES6 可以自定义原生数据结构(比如Array、String等)的子类,这是 ES5 无法做到的。

    上面这个例子也说明,extends关键字不仅可以用来继承类,还可以用来继承原生的构造函数。因此可以在原生数据结构的基础上,定义自己的数据结构。
    注意,继承Object的子类,有一个行为差异。

    class NewObj extends Object{
      constructor(){
        super(...arguments);
      }
    }
    var o = new NewObj({attr: true});
    o.attr === true  // false
    

    因为 ES6 改变了Object构造函数的行为,一旦发现Object方法不是通过new Object()这种形式调用,ES6 规定Object构造函数会忽略参数。

    相关文章

      网友评论

          本文标题:为什么ES5无法继承原生构造函数?

          本文链接:https://www.haomeiwen.com/subject/aogxxqtx.html