Please check the code below -
custom_array.push(...) is working
but
custom_array[i] = "n"
is not working.
There are a couple more things which i am not sure why it is not working. Please note the comments with "?" which is not working. Please refer fiddle - http://jsfiddle.net/vc0bbm3d/
The reason that setting items using bracket syntax doesn't work for your object inheriting an array, is that it's not actually an array.
An array has special code for handling property assignment (which is what you do with the bracket syntax) when the property name is an integer. If the index is outside the current length, the length property is adjusted.
When you assign a value to a property in your object, there is no special code to handle the length. The property is just assigned as usual, and the length is never adjusted. As the object already has code for handling what's happening when you use the bracket syntax, the array that it inherts never comes into play.
For the bracket syntax to work in that way, the object has to be an actual array.
try
ar[3] = 2;
ar.length =4
That way it knows you have added something.
Here's an example of what I mean when I say create a layer around the default array object to extend functionality:
var SuperArray = function(){
this.arr = Array.prototype.slice.call(arguments);
};
//abstraction of default array functionality
SuperArray.prototype.set = function(index, value){
this.arr[index] = value;
return this;
};
SuperArray.prototype.unset = function(index){
this.arr.splice(index, 1);
return this;
};
//extension of default array functionality
SuperArray.prototype.consoleList = function(){
var arr = this.arr;
for(var i = 0, l = arr.length; i < l; i++){
console.log(arr[i]);
};
return this;
};
var extArr = new SuperArray(1,2,3);
extArr.set(2, 25); //does array[2] = 25;
extArr.unset(1); //removes array[1]
extArr.consoleList();//console.logs all items in array
extArr.set(2, 25).unset(1).consoleList();//same thing
this simple object accepts arguments and sets them directly into an array, which we then manipulate how we wish. You can then add any utility functions that you need, check for existing array functionality, etc.
Related
Good morning/afternoon
I Want to create an object whitch simulate an array, for new browsers no pb I change the proto of an array with mine but for oldest version of IE i need to know the length of my false array by finding the last index.
I have found a way for IE:
var getLastPos = function(){
for( var i in falseArray){
//do nothing
}
return i
}
but if a faster way exists, it rather like. I try to pass regex to lastindexof
but it seems don't work
thanks.
when you want to find the last index from the array, use
<array>.length
So you do not need the for loop, and your function, use
falseArray.length
If you need the value from the last position use something like this:
falseArray[falseArray.length-1]
//decrement by one, because the index from the array starts by 0
I hope this is helpful.
Thks for you reply,
It was a old question, but I will answer, my goal was to create a false array in order to not polluate prototype.
By false array I mean an object who have the same behavior than a array with .length property and the use of '[]'.
My conclusion is that it is only possible at the class level with new Browser that allow to modify the proto
Ex:
var myClassArray = function(){
var obj = []
obj.__proto__ = myClassArr.prototype
return obj
}
myClassArr.prototype = Array;//inheritance
myClassArr.prototype.last = function(){
return this[this.length-1]
}
or for old browser at object level
var myClassArray = function(){
var obj = []
obj.last= function(){
return this[this.length-1]
}
return obj
}
how to use it:
var myArray = new myClassArray;
console.log(myArray.length) //0
myArray[5]=1;
console.log(myArray.length) //6
console.log(myArray.last()) //1
Conclusion:
Modifiying the proto is a bad idea about perf and old browser.
you can improve the code for old browser by creating function outside the class constructor else browser will duplicate function.
var last = function(){
return this[this.length-1]
}
var myClassArray = function(){
var obj = []
obj.last = last
return obj
}
var a = new myClassArray
var b = myClassArray()//In fact new is facultative
b.last == a.last //same ref no duplication
I want to access (get/set) a nestedJS object with a variable.
For example, static it would look like that:
$obj.children.12.children.32.Name; // Returns "Foo"
Now I have an "Route" array (or whatever is easy too handle):
["children",12,"children",32,"Name"]
And want to get the value of the object.
Like I read here on Stackover, there is an very easy way to do it (Solution 2).
But, now I want to change the value for the passed key/route. Is there any way to do that?
Thank you very much!
Edit:
I can use jQuery/Angluar-Features, if it helps me.
Borrowing code from the accepted answer on the post you've linked to, we can trivially make a getter:
function getFromPath(obj, pathArray) {
var res = obj;
for (var i=0; i<pathArray.length; i++) { res = res[pathArray[i]]; }
return res;
}
We call this with getFromPath($obj, ["children",12,"children",32,"Name"]);.
Since you want to transform this getter function into a setter, you want to set a property on the second-to-last object. We can do this by stopping the loop one iteration early and then performing set with the final property name on the object:
function setToPath(obj, pathArray, valueToSet) {
var res = obj;
// note the `length - 1` here: we don't go to the end of the path
for (var i=0; i<pathArray.length - 1; i++) { res = res[pathArray[i]]; }
// res is now the second-to-last object in the path,
// and we'll set the final value as a property on the object
var finalKey = pathArray[pathArray.length-1];
res[finalKey] = valueToSet;
}
We call this with setToPath($obj, ["children",12,"children",32,"Name"], "Dana");.
Alternatively, if you wanted to do this with just a getter, you could shorten your path by one item and perform the set on the result from the getter:
var secondToLast = getFromPath($obj, ["children",12,"children",32]);
secondToLast["Name"] = "Dana";
I have a bit of Javascript where I'm POSTing my form with an XMLHttpRequest, which otherwise works fine, but when I try to add the SELECT values to the array of INPUT values, it seems Javascript has lost its mind (or I have).
This function just builds the "name1=value1&name2=value2" string and passes it along.
The code:
function sendTheForm() {
var postData = '';
var inputArr = document.getElementsByTagName('input');
if (inputArr.hasOwnProperty(length)) alert("ARRAY!!");
var selects = document.getElementsByTagName('select');
var tmpObj = new Object();
for (var i = 0; i < selects.length; i++) {
tmpObj.name = selects[i].name;
tmpObj.value = selects[i].value;
inputArr.push(tmpObj);
}
for (var i = 0; i < inputArr.length; i++) {
if (inputArr[i].value) {
if (postData.length) postData += '&';
postData += inputArr[i].name;
postData += '=';
postData += escape(inputArr[i].value);
}
}
makeHttpReq(postData)
}
The error I get in FireFox is: "inputArr.push is not a function" It does say it's an Array.
Now, besides the fact that it's a method (not a function), it seems something is going badly wrong here, it's right under my nose and I can't see it. Help?
Earlier, I tried doing:
len = inputArr.length;
inputArr[len].name = ...
and also got an error that inputArr[31] was undefined. This is probably obvious, but I'm not seeing it. Help?
Having a .length property does not mean that it is an array. getElementsByTagName() returns a DOM 2 NodeList, not an Array.
As Phrogz already said, checking for a length property is NOT a way of checking for an array.
There's only one way to do that, so it works in ALL cases.
And that is using Object.prototype.toString.call(object).slice(8, -1).
Which gives you the Class value.
Value Class Type
-------------------------------------
"foo" String string
new String("foo") String object
1.2 Number number
new Number(1.2) Number object
true Boolean boolean
new Boolean(true) Boolean object
new Date() Date object
new Error() Error object
[1,2,3] Array object
new Array(1, 2, 3) Array object
new Function("") Function function
/abc/g RegExp object (function in Nitro/V8)
new RegExp("meow") RegExp object (function in Nitro/V8)
{} Object object
new Object() Object object
The reason why this isn't working is because the inputArr variable is actually a node list, not a real array.
If you do want it to be an array, you'd loop through it and add all the nodes in it to a real array or you can do this:
var node_array = Array.prototype.slice.call(node_list);
After creating a multi-dim array like this, how do I sort it?
Assuming 'markers' is already defined:
var location = [];
for (var i = 0; i < markers.length; i++) {
location[i] = {};
location[i]["distance"] = "5";
location[i]["name"] = "foo";
location[i]["detail"] = "something";
}
For the above example, I need to sort it by 'distance'.
I've seen other questions on sorting arrays and multi-dim arrays, but none seem to work for this.
location.sort(function(a,b) {
// assuming distance is always a valid integer
return parseInt(a.distance,10) - parseInt(b.distance,10);
});
javascript's array.sort method has an optional parameter, which is a function reference for a custom compare. the return values are >0 meaning b first, 0 meaning a and b are equal, and <0 meaning a first.
Have you tried this?
location.sort(function(a,b) {
return a.distance - b.distance;
});
Both sort functions posted so far should work, but your main problem is going to be using location as a variable as it is already system defined.
I am trying to remove an element from a Javascript associtive array using the value to find it, but I am having trouble. I have tried splice and JQuery's grep method and neither have worked for me. This is what I currently have.
var array_path = new Array();
function bulk_upload(){
var temp_array = new Object();
for (var i = 1; i<8; i++){
temp_array[i] = $('#path' + i).val();
if(temp_array[i]!='' && temp_array[i]!=null){
array_path['path' + i] = $('#path' + i).val();
}
}
process_txt();
}
function process_txt(){
//alert(array_path.indexOf(full_path)); //returns nothing
var removed_element = array_path.splice(getKey(array_path), 1);
//array_path = $.grep(array_path, function(val) { return val != full_path; });
alert(removed_element);//return nothing, just blank alert box
}
function getKey(data) {
for (var prop in data)
return prop;
}
The way to do this is to use the delete operator.
delete array_path[getKey(array_path)]
Some Background Information
In JavaScript, almost everything descends from Object.prototype. JavaScript, being an open and dynamic language allows you to create/modify properties of objects by simple assignment. This is very similar to what an associative array -- a structure that contains keyed values.
Under the hood an array is just an object that descends from Array.prototype with numeric keys and a special property called length. The length property just returns one greater than the highest numeric property. In essence, an Array is an object with different semantics.
If you're wanting an associative array then Array is not the object you want to descend from. You would want to descend directly from Object. There are two ways to do that, you could either use the new operator or an empty object literal. The syntax for both is below:
var o = new Object();
var o = {};
The second is preferred since it's a little bit more concise.
I wrote a blog post about this a while back, have a look if you want a little bit more info.
There is no such thing in JavaScript as an "associative array" per se. The data structure which corresponds to this concept is simply a JavaScript Object.
Of course, a JavaScript Array (like essentially everything in JavaScript) is an Object, but one with additional capabilities. So you can use an Array as a key-value map, but it's really not the correct structure for that.
To remove a key from an Object, you just do something like this:
var myObj = {};
var myKey = "blah";
myObj[myKey] = 1234; // Adds or updates value for "blah" to 1234.
delete myObj[myKey]; // Removes key-value pair for "blah".
Have you tried delete hash.someKey; ?
You can give your object a remove method, or use apply or call to use another object's remove method, if defined.
function myObj(members){
for(var p in members) this[p]= members[p];
}
myObj.prototype.remove= function(val){
for(var p in this){
if(this[p]=== val) delete this[p];
}
return this;
}
myObj.prototype.toString= function(){
var A= [];;
for(var p in this){
if(this.hasOwnProperty(p)){
A.push(p+':'+this[p])
}
}
return '{'+A.join(', ')+'}';
}
var O= new myObj({a: 1, b: 10, c: 100});
alert(O)
O.remove(10);
alert(O)
I'm not psychic, so I can only guess that you wanted to accomplish something like this:
var paths = [];
function getPaths() {
for(var i = 1; i < 8; ++i) {
var value = $('#path' + i).val();
if(value) paths.push(value);
}
}
function process() {
var firstPath = paths.shift();
// do stuff
}
getPaths();
if(paths.length) process();