类的简单认识(四)

234 阅读3分钟

九.原生构造函数的继承

  1. 所谓的原生构造函数就是:String,Boolean,Number,Date,Array...
  2. 在ES6之前这些原生构造函数是无法继承的!
  • Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
  • 所以Object.create方法的第一个参数是新创建对象的原型指向的对象
  • 第二个参数可以是Object.defineProperties的对应参数对象,可选
  • 第二个参数也可以是其他的属性对象,如{foo:'ee'}就是给新创建对象增加了foo属性
 function Arr(){
  Array.apply(this,arguments)
 }
 Arr.prototype = Object.create(Array.prototype,{
  constructor:{
   valueArr,
   writabletrue,
   configurabletrue,
   enumerabletrue 
  }
 })
 // 虽然看起来是创建了一个继承Array的对象,但是这个函数的行为和Array不一样
 let a = new Arr()
 a[0] = 1;
 console.log(a) //0: 1
 console.log(a.length// 0,长度没有改变。
 a.length = 0
 // 设置数组长度为0,但是依旧可以得到数组元素
 console.log(a) // myArr [0: 1]
  • 上面的继承方式不能让新对象获得原生构造函数的内部属性,也就是没有绑定this
  • ES6中允许继承原生构造函数继承子类,这种方式是先新建父类的实例对象!
  • 然后再通过子类的构造函数调用super来调用父类的构造函数,使得子类可以继承父类的所有行为
 class Arr extends Array{
  constructor(...args) {
      super(...args)
  }
 }
 let arr = new Arr()
 arr[0] = 2
 console.log(arr) // 0: 2 ; length: 1
 console.log(arr.length) // 1
 // 修改length属性
 arr.length = 0
 console.log(arr) //Arr []
 // 完全继承了构造函数的所有行为

构造函数继承的应用

  • 因为可以继承原生构造函数,所以我们可以在原生构造函数基础上定义自己的数据结构!
 // 新建一种数据结构,可以在原有数据结构的基础上尽情自定义
 // 个人觉得这种思想还是很重要的
 class Arr extends Array{
  constructor(){
   super()
   // 历史栈
   Object.defineProperty(this,'history',{
    enumerable:false,
    configurablefalse,
    writabletrue,
    value:[[]]
   })
  }
  // 提交到本地仓库,类似git 
  commit(){
   this.history.push(this.slice())
  }
  // 版本回退(回退到上一次commit的版本,重复revert没用)
  revert(){
   this.splice(0this.length, ...this.history[this.history.length-1])
  }
  // 对原有数据结构的方法进行重写
  push(val){
   console.log('重写')
   this[this.length] = val;
  }
 }
 let a = new Arr()
 a.push(1)
 a.commit()
 console.log(a)  //Arr [1, history: Array(2)]
 for(let i=0;i<a.length;i++){
  console.log(a[i]) // 1
 }
 // 设置history属性不可枚举
 console.log(Object.keys(a)) //["0"]
 // console.log(Object.getOwnPropertyDescriptor(a,'length'))
 a.push(2)
 console.log(a) //Arr(2) [1, 2, history: Array(2)]
 a.revert()
 // 回退到之前commit的版本
 console.log(a) //Arr [1, history: Array(2)]

十.mixin模式

  1. mixin指的是多个对象合成一个新的对象,使得新对象具有各个组成员的接口
  2. vue中的mixins就是这个原理!常用的就是在mixins机制下使用created等生命周期函数(一开始看项目代码就忽略了这一点)
 // 最简单的思想实现:
 let a={name:'ss'}
 let b={age:33}
 console.log({...a,...b}) //{name: "ss", age: 33}
  • 注意点:由于之前没有注意类名首字母要大写的规范,所以修改过一次,上面代码如果有问题就看看类名

本文参考阮一峰ES6教程