处理es6继承原生数组兼容性问题

处理es6继承原生数组兼容性问题

描述:

在vue开发过程中,想要实现一个自定义的类实现继承原生数组,这样即可以用原生数组的功能,还可以拓展自己的功能,并且不用改变原生数组原型不会影响原来数组的功能。
代码如下

class ExtendArray extends Array {
  replace(fn, item) {
    const index = this.findIndex(fn)
    this.splice(index, 1, item)
    return this
  }
  findAndReplace(fn, item) {
    const index = this.findIndex(fn)
    this.splice(index, 1, item)
    return this
  }
  findAndMerge(fn, item) {
    const index = this.findIndex(fn)
    Object.assign(this[index], item)
    return this
  }
}

const eArr = new ExtendArray(1, 2, 3)
eArr.replace(val => {
	return val === 2
}, 4)
console.log(eArr)//ExtendArray(3) [1, 4, 3]

上面这个代码跑谷歌浏览器中没什么毛病,不过在ie下可就没那么又好了。项目中引用有babel插件正常情况会自动做降级处理的,不过好像不支持处理对原生js对象继承,后来找到一种方法,配置.babelrc文件
方法如下:

解决方案1

配置.babelrc文件如下:

{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2"
  ],
  "plugins": ["transform-vue-jsx", "transform-runtime", ["transform-builtin-extend", {
    "globals": ["Error", "Array"]
}]]
}

注意在globals:[]中添加 Array, 这样降级处理的时候就支持对原生数组的继承了。

解决方案2:

使用es5 写法,上面添加配置后可以解决问题,但是在某些情况还是会出错,最好我只好自己实现一个继承原生数组的类。代码如下:

// 定义原型的方法
const methods = {
  constructor: ExtendArray,
  replace(fn, item) {
    const index = this.findIndex(fn)
    this.splice(index, 1, item)
    return this
  },
  findAndReplace(fn, item) {
    const index = this.findIndex(fn)
    this.splice(index, 1, item)
    return this
  },
  findAndMerge(fn, item) {
    const index = this.findIndex(fn)
    Object.assign(this[index], item)
    return this
  }
}

// 数组继承类,解决babel 不能处理es6直接继承原生数组的问题
function ExtendArray(...param) {
  const arr = new Array(...param)
  // 继承数组实例的属性
  Object.assign(this, arr)
  Object.defineProperty(this, 'length', {
    value: arr.length,
    enumerable: false// 定义length属性为不可枚举
  })
}
const prototype = Object.create(Array.prototype)
// 定义原型上的方法, 并且不能枚举
Object.keys(methods).map(key => {
  Object.defineProperty(prototype, key, {
    value: methods[key],
    enumerable: false// 不可枚举
  })
})
// 设定原型
ExtendArray.prototype = prototype

export default ExtendArray

上面方法首先定义ExtendArray 构造方法,在构造内部

function ExtendArray(...param) {
// 注意这里调用 Array.call(this, ...param)没有将数组的属性复制到我的this 实例上,具体原因不太清除
  const arr = new Array(...param)
  // 继承数组实例的属性
  Object.assign(this, arr)
  Object.defineProperty(this, 'length', {
    value: arr.length,
    enumerable: false// 定义length属性为不可枚举
  })
}

注意: 在内部没有调用 Array.call(this, …param),是因为,我这么尝试之后,发现新创建的对象并没有被赋予数组实例的属性,所以我只好用Object.assign手动复制。注意数组中length 是不可枚举的,这里我也通过Object.definPropery 设置其 enumerable 为false,否则会通过for in 循环遍历出来。
然后用Object.create(Array.prototype) 创建一个继承数组的原型对象。然后在将定义好的原型方法设置到原型对象上,通常原型上的方法是不应该被枚举的,这里同样设置为不可枚举。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值