我创建了一个JavaScript应用程序,它有很多数组操作(排序,过滤等)。
目前我的功能是这样的:
function (myArray, arg1, arg2,...)
其中myArray是我正在处理的数组,而arg1,arg2,...是函数用来修改数组的参数。
我认为在对象和参数之间进行明确的分离会更简洁(la jQuery):
myArray.function(arg1, arg2,...)
我知道我可以使用Array.prototype将我的函数添加到所有数组中,但是这看起来太重了,因为我添加的函数对我的情况来说非常具体,而且对数组一般没有意义。我也知道我可以创建一个对象,但是我不会受益于JavaScript中可用的数组方法(indexOf,filter等)。
有没有办法可以创建自己的数组对象,继承默认的数组方法并允许我添加自己的数组对象?
答案 0 :(得分:8)
你有两个选择:
选项一是通过向其添加新方法来扩展Array
对象:
Array.prototype.myMethod = function(arg1, arg2)
{
// Use 'this' to access the array.
}
优点是每个javascript数组现在都有这个额外的方法。当多个(外部)javascript库尝试添加相同的方法时,这也是一个缺点。此外,这种新方法将出现在for(var item in myArray)
构造中,这可能会有问题。
选项二是为扩展阵列创建“工厂方法”:
function MyExtendedArray = function()
{
var array = [];
array.myMethod = function(arg1, arg2) {
// Use 'this' or 'array' to access the array.
};
return array;
};
现在你可以写这个来创建一个新的扩展数组:
var arr = MyExtendedArray();
答案 1 :(得分:5)
您只需将函数直接添加到对象而不是原型:
var myArray = new Array();
myArray.myFunc = function(){ /* do stuff! */ };
myArray.myFunc();
答案 2 :(得分:4)
没有。 Array
不能被子类化,并且仍然像数组一样。具体来说,length
属性不会更改以反映从数组中添加或删除的元素。
function MyArray() {}
MyArray.prototype = [];
MyArray.prototype.constructor = MyArray;
var instance = new MyArray;
instance[0] = 0;
alert(instance.length); // alerts 0
发生这种情况的原因是因为只有通过new Array
创建的对象或像[]
这样的句法糖才能对长度进行特殊处理。
上面的new MyArray
创建了一个常规对象,其原型是Array
,但是new
运算符没有任何内容可以检查对象的原型是否为Array
并设置特殊的length
处理。
答案 3 :(得分:0)
是的,只需使用jQuery.extend
扩展Array prototype
即可
答案 4 :(得分:0)
我创建了这个数组,这是我的数组版本,但是对此数组进行了一些修改,您无法像使用原始数组一样更改长度
let ary = [1,2,3];
console.log(ary.length); //3
ary.length = 999;
console.log(ary.length); //999
因为我使用get函数来获取长度并使用闭包来保存原始数组长度的值
let myArray = new MyArray(1,10); //new MyArray(from,to)
console.log(myArray.length); // 10
myArray.length = 999;
console.log(myArray.length); // 10 //still 10 because .length is a get function
我的数组的代码是
let _getlength = {}, _inclength = {}, _declength = {};
class MyArray{
constructor(from, to)
{
this.key = Symbol('ignore this key');
//i make it a closer because i don't want any one to change the length
// by this my length become private and can be only incremented by one by "_inclength()" function or
[_getlength[this.key], _inclength[this.key], _declength[this.key]] = (
() =>
{
let length = 0;
let getLength = () =>
{
return length;
};
let inclength = () =>
{
length++;
this[length - 1] = 0;
return length;
};
let declength = () =>
{
return --length;
};
return [getLength, inclength, declength];
}
)();
if (from != null || to != null)
{
for (let num = from; num <= to; num++)
{
this.push(num);
}
}
}
push(value)
{
this[this.IncreaseLengthByOne() - 1] = value;
}
unshift(value)
{
this.addAt(0, value)
}
addAt(index, value)
{
this.IncreaseLengthByOne();
for (let i = this.length - 2; i >= index; i--)
{
this[i + 1] = this[i];
}
this[index] = value;
}
removeAt(index)
{
for (let i = index; i < this.length - 1; i++)
{
this[i] = this[i + 1];
}
this.pop();
}
pop()
{
_declength[this.key]();
delete this[this.length];
}
get length()
{
return _getlength[this.key]();
}
IncreaseLengthByOne()
{
return _inclength[this.key]();
}
forEach(callback)
{
for (let i = 0; i < this.length; i++)
{
callback(this[i], i, this);
}
}
map(callback)
{
let myArray = new MyArray();
for (let i = 0; i < this.length; i++)
{
myArray.push(callback(this[i], i, this));
}
return myArray;
}
// if you don't know what it is then go and learn what generators are! what Symbol(primitive type) is and what Symbol.iterator is then
// come back
* [Symbol.iterator]()
{
for (let i = 0; i < this.length; i++)
{
yield this[i];
}
}
}
示例: 创建一个名称数组,并在其中添加“ Ali”,“ Hadi”,“ Amber”
let names = new MyArray();
names.push('Ali');
names.push('Hadi');
names.push('Amber');
console.log(names); // MyArray {0: "Ali", 1: "Hadi", 2: "Amber"}
通过在末尾添加姓氏“ Nawaz”来修改每个名称像“ Ali”成为“ Ali Nawaz”
let fullNames = names.map(nam => nam +' Nawaz');
console.log(fullNames); //MyArray {0: "Ali Nawaz", 1: "Hadi Nawaz", 2: "Amber Nawaz"}