I have created a JavaScript application that has a lot of array manipulations (sorting, filtering, etc.).
Currently my functions are like this:
function (myArray, arg1, arg2,...)
where myArray is the array I am working on, and arg1, arg2,... are the arguments used by the function to modify the array.
I am thinking that it would be neater to have a clear separation between the object and the arguments (a la jQuery):
myArray.function(arg1, arg2,...)
I know that I could use Array.prototype to add my function to all arrays, but this seems too heavy as the functions I add are really specific to my case and don't make sense on arrays in general. I also know that I could create an object, but then I wouldn't benefit from the array methods available in JavaScript (indexOf, filter, etc.).
Is there a way I could create my own array object, that would inherit the default array methods and allow me to add my own?
I have created a JavaScript application that has a lot of array manipulations (sorting, filtering, etc.).
Currently my functions are like this:
function (myArray, arg1, arg2,...)
where myArray is the array I am working on, and arg1, arg2,... are the arguments used by the function to modify the array.
I am thinking that it would be neater to have a clear separation between the object and the arguments (a la jQuery):
myArray.function(arg1, arg2,...)
I know that I could use Array.prototype to add my function to all arrays, but this seems too heavy as the functions I add are really specific to my case and don't make sense on arrays in general. I also know that I could create an object, but then I wouldn't benefit from the array methods available in JavaScript (indexOf, filter, etc.).
Is there a way I could create my own array object, that would inherit the default array methods and allow me to add my own?
Share Improve this question asked Feb 10, 2012 at 19:24 ChristopheChristophe 28.1k29 gold badges101 silver badges143 bronze badges 2- 3 keep using the function, you don't need everything in oop – dynamic Commented Feb 10, 2012 at 19:27
- 2 Right, but I like how clean it is, for example for chaining or defining default options/arguments. – Christophe Commented Feb 10, 2012 at 19:31
5 Answers
Reset to default 10You've got two options:
Option one is to extend the Array
object by adding new methods to it:
Array.prototype.myMethod = function(arg1, arg2)
{
// Use 'this' to access the array.
}
The advantage is that every javascript array will now have this extra method. This can also be a disadvantage when multiple (external) javascript libraries try to add the same methods. Furthermore, this new method will appear in for(var item in myArray)
constructs which can be problematic.
Option two is to create a "factory method" for your extended array:
function MyExtendedArray = function()
{
var array = [];
array.myMethod = function(arg1, arg2) {
// Use 'this' or 'array' to access the array.
};
return array;
};
Now you can write this to create a new extended array:
var arr = MyExtendedArray();
No. Array
cannot be subclassed and still behave like an array. Specifically, the length
property will not change to reflect elements that are added or deleted from the array.
function MyArray() {}
MyArray.prototype = [];
MyArray.prototype.constructor = MyArray;
var instance = new MyArray;
instance[0] = 0;
alert(instance.length); // alerts 0
The reason this happens is because only objects that are created via new Array
or syntactic sugar like []
have the special handling around length.
The new MyArray
above creates a regular object whose prototype is an Array
, but there is nothing about the new
operator that checks whether the prototype of an object is an Array
and sets up the special length
handling.
You can simply just add the function directly to your object rather than to the prototype:
var myArray = new Array();
myArray.myFunc = function(){ /* do stuff! */ };
myArray.myFunc();
i create this which is my version of array but with some modifications in this array you cant change the length like with the original array
let ary = [1,2,3];
console.log(ary.length); //3
ary.length = 999;
console.log(ary.length); //999
because i use get function to get my length and use closures for saving the value of original array length
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
the code of my array is
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];
}
}
}
examples: create an array of names and add "Ali", "Hadi", "Amber" to it
let names = new MyArray();
names.push('Ali');
names.push('Hadi');
names.push('Amber');
console.log(names); // MyArray {0: "Ali", 1: "Hadi", 2: "Amber"}
modify every name by adding there last name "Nawaz" at the end Like "Ali" become "Ali Nawaz"
let fullNames = names.map(nam => nam +' Nawaz');
console.log(fullNames); //MyArray {0: "Ali Nawaz", 1: "Hadi Nawaz", 2: "Amber Nawaz"}
Yes, just extend the Array prototype
with jQuery.extend