Array is not array - javascript

I am running
var n = [];
jQuery.toJSON( n );
On one page I get "[]" on the other ""[]"". On both pages I run the same jQuery version with a toJson Plugin.
In Firefox DOM I can see both arrays have the same function names, but ... different:
all b(B, A)
any j(B, A)
all all(iterator, context)
any any(iterator, context)
I guess there are some Array.prototype functions before my script. That causing the arrays to be different. I can't change the other code I have to somehow deal with this.
I tried new Array() and jQuery.makeArray(n), still same result. I actually don't care that the arrays are not equal but how do I get the same JSON code for this? It's getting worse if I have strings in the array: ""[\"a\", \"b\"]""

The extra quotes are caused by the
Array.prototype.toJSON
function that is defined by the Prototype library and possibly other libraries as well. This function is called by jQuery.toJSON (or JSON.Stringify() for that matter) and produces the extra quotes. If you would use
delete Array.prototype.toJSON // remove toJSON for all Arrays
//or
delete n.toJSON // remove toJSON for specific Array
before you do the jQuery.toJSON, that should work!
As another suggestion, it is better to use
JSON.stringify(object)
instead of jQuery.toJSON. It is supported natively in most browsers. If you want to be sure it works everywhere, use https://github.com/douglascrockford/JSON-js, it is the basis used for the JSON.stringify() function.
For JSON.stringify(), see https://developer.mozilla.org/En/Using_native_JSON for more info.

My dirty hack for this is:
function cleanJson(s)
{
if (s[0] == '"')
{
s = s.substring(1, s.length-1).replace(/\\"/g,'"');
}
return s;
}
Does the job, but I am still looking for a cleaner solution.

Related

Why assign the string 'prototype' to a variable then use it to set the prototype of an object?

I just came across this code for a classList polyfill and I can't understand why the developer chose to do the following:
var protoProp = "prototype";
... later in the code...
ClassList[protoProp] = [];
What's wrong with ClassList.prototype = []? I can't think of any reason why they would do this. What am I missing?
It looks to be for minimisation, where that value can be converted into
ClassList[v]=[];
rather than
ClassList.prototype = [];
The protoProp variable is used several places instead of prototype and would save a few bytes in total
in my last project i needed to minify & obfuscate my code and i convert all objects like this
arr.length ===> arr["length"];
str.replace("a","") ===> str["replace"]("a","");
Element.prototype.colorize ===> Element["prototype"]["colorize"]
and every thing works very well
now i have strings
length , replace , prototype , colorize
and we have multiple ways to obfuscate this strings to be more difficult to read.

parse json object That stringify Twice

How can i parse some object that stringify twice?
Most of the time in my code it is not problem but some times it stringify twice, and I can not trace the code to find my problem.
My JSON object something like this:
""[{\"name\":\"trane\",\"price\":\"150000\",\"order\":\"\",\"sale\":\"\",\"printedPic\":\"\",\"remainingPic\":\"\",\"locationEncome\":\"\"}]""
It's definitely best to figure out where and why it's stringifying twice, but you can just parse twice if you have to.
JSON.parse(JSON.parse("JSON STRING HERE"))
Edit
Potentially you're stringifying an already stringified object, this could help you figure out what is going wrong.
Add this function to your code and then replace your JSON.stringify calls to JSON.stringifyIfObject calls. Just use this as a means of debugging though, I wouldn't put this into production.
JSON.stringifyIfObject = function stringifyIfObject(obj){
if(typeof obj == "object")
return JSON.stringify(obj);
else{
alert("found already stringified object")
return obj;
}
}
This post is a little bit old but I had the same problem today and it was caused by a third party library.
Javascript library Prototype.js applies JSON.stringify() twice when it is used in version 1.6.x (it seems that this bug was removed in version 1.7)
The following code :
var test = ["banana"];
JSON.stringify(test);
will give you the following result :
""[\"banana\"]""
instead of (normally expected) :
"["banana"]"
Here is my source :
https://github.com/krinkle/jquery-json/issues/35
If that happens to you, the best option is to upgrade that library if you can.

Can you add a function to a hijacked JavaScript Array?

This question is related to What are the best practices to follow when declaring an array in Javascript?
Let's say a client, let's call them "D. B. Cooper", has a first requirement that the following code must run before any other JavaScript code:
Array = function(){
alert('Mwahahahaha');
};
Furthermore, Cooper requires that custom functions must be added to the built in Array object (not the hijacked one). For example, if Array was unhijacked, this would be done with:
Array.prototype.coolCustomFunction = function(){
alert('I have ' + this.length + ' elements! Cool!');
};
Which would afford:
var myArray = [];
myArray.coolCustomFunction();
However, this is not compatible with the first requirement. Thus, how can you best fulfill both of D. B. Cooper's requirements?
Note: D.B. even wrote a test fiddle to help make sure solutions meet his requirements...what a guy!
Update:
For those of you who like a challenge: please try to find an unhijackable cross-browser solution to this problem. For example, here's an even more hijacked test case (thanks for reformatting this Bergi) that hijacks Array, Object, Array.prototype.constructor, and Object.prototype.constructor. Thus far, it looks like there may be a browser-specific solution to this (see Bergi's comment on his answer, and let us know if you find a way to hijack it in FF), but it is unclear at this point if there is a cross-browser solution to this.
Whatever your Array function/constructor is, the literal syntax for arrays will always generate "real" arrays with their [[prototype]] set to the native array prototype object (once, this was a security vulnerability). So, you can always access that by using
Object.getPrototypeOf([])
even if Array or [].constructor are hijacked. (Will of course not work when Object is hijacked, then it get's really complicated)
(Brought D.B. down!)
If you want to use a workaround, in FF the following line will always work (and is not hijackable):
[].__proto__.coolCustomFunction = coolCustomFunction;
Since Array is not necessarily equal to [].constructor, you could use [].constructor to refer to the original Array function since this is hardwired and Array = function(){} won't alter it.
Array = function () { alert("foo")};
// this will always point to the original Array
[].constructor.prototype.foo = "bar";
var myArray = [0, 1];
alert(myArray.foo) // alerts "bar"
http://jsfiddle.net/yXPJ8/5/
Yes ... you just did ... but you created the array using [] .. if you use new Array() it works fine ...
See example here

Using jasmine to compare arrays fails in ie8

Apparently ie8 has three properties that get appended to the resulting array from a call to String.prototype.match():
input, index and lastIndex
(MSDN Documentation)
The result is that array comparison fails when using Jasmine's .toEqual() matcher.
I'm still working my way up the learning curve on unit testing, so I'm just curious of what the right way is to do deal with this failure.
The following works but seems a bit lame:
numArray = str.match(/\d+(\.\d+)?/g);
if (numArray && numArray.input) {
delete numArray.index;
delete numArray.input;
delete numArray.lastIndex;
}
Underscore's 'difference' method can help -
expect(_.difference(['item1', 'item2'], ['item1', 'item2'])).toEqual([]);
http://underscorejs.org/#difference
I think #monkeyboy's answer is not correct.
Since underscore.difference() returns the elements of the first array that are not present in the second array: _.difference([1],[1,2]); is also [] so the test will pass when it shouldn't. I couldn't find a way to solve this using underscore.
So i'm using:
expect(JSON.stringify(result)).toBe(JSON.stringify(expected));
which works as expected.
Anyway, i'd like to know how others are doing this.

weird IE 7 javascript problem

I have this javascript code working in firefox, chrome, and safari
for (idx in all_auction_ids){
alert(all_auction_ids[idx]);
};
for the above, instead of getting the values in all_auction_ids, the first value I get is text of type function that looks like a for loop!
But if I run the code below, it works fine.
for (idx=0;idx<all_auction_ids.length;idx=idx+1){
alert(all_auction_ids[idx]);
};
edit: updates
I did some debugging and found out that, adding Orbited and stomp.js is probably doing something with the array!
for now i am using Tracker1's suggestion jquery's $.each.
more info:
http://groups.google.com/group/orbited-users/browse_thread/thread/7fd658cfb166e9fa
array with the problem
http://bayimg.com/fAnhaAaBb
array without the problem
http://bayimg.com/FaNhEAabb
JavaScript's for/in construct is traditionally for iterating over object member names, not array indices. The more forward-thinking browsers have added features like hidden properties to help cases like Array enumerate in the way you would expect, but IE stilll does it the old-school way and gives you Object members like the 'toString' method when you use for/in over an Array.
The indexed-for is still the canonical JavaScript array loop. (Although you probably mean 'for (var idx=...', and 'idx++' is more common.)
It's worth noting that some libraries such as prototype.js extend Array, so that they have additional properties beyond the internal indexes. This breaks for x in y notation beyond, as other mentioned, that IE will iterate properties. for i=0...i++ is preferred.
Also worth noting is jQuery, prototype and others offer a .each(fn) notation that I actually prefer.
I agree with #bibince that you probably should be using the "for(var i = 0..." syntax, but there is no reason that the syntax you chose should not work unless you have done something strange in your creation of all_auction_ids. How are you initializing your array?
Arrays in JavaScript are just objects with a special auto-incrementing feature, but in reality they are not much different that an anonymous object. Try this in Firebug:
var a = ['a','b','c'];
a.d = 'd';
for(var i in a) console.log(i, a[i]);
or paste this into your address bar in IE and hit enter:
javascript:var a = ['a']; a.d = 'd'; for(var i in a) alert(a[i]); alert(a.length);
EDIT:
I doubt this is your problem, but do you have the same problem if you use:
var all_auction_ids = [];
rather than
var all_auction_ids = new Array();
If that doesn't help then could you post a little more of your code to give us a better idea of how you are populating all_auction_ids?
This topic on the YUI blog is germane to your problem.
I've been having similar problems lately creating "select all / clear all" buttons for lists of checkboxes. In Firefox and Chrome they work fine, but in IE7/8 they don't. I'm not using any frameworks or external libraries, all the JavaScript is my own, it's fairly straightforward stuff, and there isn't much of it. I build the array of input elements using getElementsByTagName, then loop through:
var allClearInputs = document.getElementsByTagName("input");
for(ac=0;ac<allClearInputs.length;ac=ac+1){
if(allClearInputs[ac].id){
var thisNameArr = allClearInputs[ac].id.split("-");
var thisName = thisNameArr[0];
if(thisName == checkName){
if((actionType == 'all' && allClearInputs[ac].checked == false) || (actionType == 'clear' && allClearInputs[ac].checked == true)){
allClearInputs[ac].click();
}
}
}
}
Works perfectly with: for(ac=0;ac<allClearInputs.length;ac=ac+1){
Fails miserably with: for(var ac in allClearInputs)

Categories

Resources