处理es6继承原生数组兼容性问题
- 描述:
- 解决方案1
- 解决方案2:
描述:
在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) 创建一个继承数组的原型对象。然后在将定义好的原型方法设置到原型对象上,通常原型上的方法是不应该被枚举的,这里同样设置为不可枚举。