I've noticed something weird. I've always thought new Array() was the same as {}, however it seems to be different as {} seems to just be an object type whereas new Array() is an Array in the Chrome debugger.
So I've been using $.param(data), where data is the data from a $.ajax() call. I notice that when i have a params1 = new Array() and a params2 = {} inside the data, they come out differently.
params1 becomes
params1[]=1¶ms1[]=2
and params2 becomes
params2[0]=1¶ms2[1]=2.
The problem is that I had been using .param(data, false) because I noticed that params1[] was being serialized incorrectly, however .param(data, false) fails for params2 and gives me params2=[object+Object].
I figure I can get around this by just using .param(data) and stripping out "[]" so that regardless of it being initialized using {} or new Array, it'll still work out correctly. But I'd like to know if there's a better solution (short of always using {} vs new Array).
Kyliod,
In javascript {} is shorthand for creating a new Object, and [] is shorthand for a "new Array()."
SO:
var myArray1 = [];
var myArray2 = new Array();
var myObject = {};
myObject.objVariable1 = 'some string or other variable data';
var myObject2 = { obj2Var1 : 'some string', obj2Var2 : 1234, obj2Var3 : true };
// do stuff
var thing1 = myArray1[1]; // get something out of myArray1
var thing2 = myArray2[2]; // get something out of myArray2
var thing3 = myObject.objVariable1; // get something out of myObject
if(myObject2.obj2Var3)
{
// do other stuff
}
Hopefully this helps you clear up your jQuery / javascript Ajax issues.
Related
Trying to return all key values of givenName but it gets nothing.
I"m new to this is...
window.location.href = 'gonative://contacts/getAll?callback=contacts_callback';
function contacts_callback(data) {
var obj = JSON.stringify(data);
var obj = JSON.parse(obj);
var givenName = obj.contacts[0].givenName;
var keys = Object.keys(obj.contacts.givenName);
document.getElementById("demo").innerHTML = keys;
}
assuming obj.contacts is an array of objects, each having a givenName property
Since obj.contacts is an array, it is unlikely to have a givenName property itself (it could, but then you wouldn't be getting that through JSON)
var keys = Object.keys(obj.contacts.givenName);
is same as
var keys = Object.keys(undefined);
and you should be getting an error in the browser developer tools console at this point
You'll want to use Array#map function as follows
function contacts_callback(obj) {
var givenNames = obj.contacts.map(({givenName}) => givenName);
document.getElementById("demo").innerHTML = givenNames;
}
Note
function contacts_callback(data) {
var obj = JSON.stringify(data);
var obj = JSON.parse(obj);
besides the obvious error (doesn't bother javascript though) of declaring the same variable twice (obj), the code is identical to:
function contacts_callback(obj) {
Note: however, that if the code inside the function were to mutate any values in obj, then, the original code should be used if you do not want to make changes to the passed in object
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 know all about JSON.stringify or JSON.parse in the sense that one serializes an object and one deserializes the string back into an object. This is great!
However, I have the following situation:
var i = new MyMagicalObject();
var oi = JSON.parse(JSON.stringify(i));
console.log(i.numFields()); // this is fine
console.log(oi.numFields()); // this throws since Object has no method 'numFields'
Basically, I'd like to treat oi as an instance of "MyMagicalObject" since that's what it is.
I'm sure there's some magic about setting the prototype on oi or something, but I'm fairly new to JavaScript. Any help would be appreciated.
You can't "store" JavaScript functions in JSON strings.
The only data types that can be stored in JSON are:
Number
String
Boolean
Array
Object
null
(source)
Anything that isn't one of those types, gets ignored:
function Test(){
this.foo = function(){
return 'bar';
}
this.theAnswer = '42';
}
var t = new Test();
alert(t.foo());
alert(JSON.stringify(t))
Your problem could be easily solved by redesigning your MyMagicalObject class. Here is an example of JSON-friendly class:
function MyMagicalObject(props) {
this.props = props || {};
}
MyMagicalObject.prototype.get = function(key) {
return this.props[key];
};
MyMagicalObject.prototype.set = function(key, val) {
this.props[key] = val;
return this;
};
MyMagicalObject.prototype.toJSON = function() {
return this.props;
};
MyMagicalObject.prototype.numFields = function() {
return Object.keys(this.props).length;
};
This realization follows two rules:
It's constructor accepts JSON representation as a first argument.
It provides toJSON method to tell JS engine how to convert its instance to JSON.
Check the following example:
var obj = new MyMagicalObject();
obj.set('foo', 42).set('bar', 'baz');
alert(obj.numFields()); // 2
var str = JSON.stringify(obj);
var obj2 = new MyMagicalObject(JSON.parse(str));
alert(obj2.numFields()); // 2
You can create a new MyMagicalObject() and then overwrite its properties with the one from oi.
var t = new MyMagicalObject();
for(var k in oi) t[k]=oi[k];
That should do the trick. If you have a more complex object (with more than 1 dimension), search for a copy function that deep copies all properties.
Add oi.prototype = MyMagicalObject.prototype; after line 3.
or
create a new object and copy the properties:
var oi2 = new MyMagicalObject();
for (var p in oi) {
if (oi.hasOwnProperty(p)) {
oi2[p] = oi[p]
}
}
console.log(oi2.numFields());
Can someone explain what is happening in the code below? I'd expect toString to get called for either both foo and bar, or neither. How is literal object notation different from adding fields to an object after it is created?
function Obj(v) {
this.v = v;
};
Obj.prototype.toString= function() {
window.alert("to string called for " +
this.v);
return this.v.toString();
}
var foo = new Obj('foo');
var bar = new Obj('bar');
// toString is not called here.
var map = {foo : 'blah'};
// toString is called here.
map[bar] = "blah2";
Why do object literals not use toString() while adding to an existing object does use toString()?
http://jsfiddle.net/pByGJ/2/
The main reason that object literals don't evaluate the identifier to the left of the colon is so you're not force to quote all literal names (as you do in JSON).
Bracket notation forces you to quote property names, if you don't, it will be evaluated as a variable.
The reason toString() does get called in the second example is because bar has to be converted to a string to be used as a property name.
In your first example, you're just creating a literal object (that is the exactly the same as {"foo" : 'blah'}). So that is never using the variable foo
If you want to create an object using a variable name, you can't use literal object notation, you have to use [] which is what forces it to call toString()
Here's a function to create objects with variable names in one expression.
function obj(key, value /*, key, value, ... */) {
var obj = {};
for (var i = 0, ln = arguments.length ; i < ln; i+=2) {
obj[arguments[i]] = arguments[i+1];
}
return obj;
}
Clearer Example
The fact that your variable names and values are the same doesn't help understanding the problem. Let me suggest this code
var foo = new Obj('fooValue');
var bar = new Obj('barValue');
var map = {foo : 'blah'};
map[bar] = "blah2";
// You expect map to be {fooValue: 'blah', barValue: 'blah2'}
// But it's {foo: 'blah', barValue: 'blah2'}
To do what you need, use my obj function
// Almost as clear as literal notation ???
var map = obj(
foo, 'blah',
bar, 'blah2'
);
// map = {fooValue: 'blah', barValue: 'blah2'} Yay!!
keys in an object literal are taken as strings, not interpreted as variables. This:
var map = {foo : 'blah'};
is equivalent to this:
var map = {"foo" : 'blah'};
and this:
var map = {};
map["foo"] = "blah";
but is completely different than this:
var map = {};
map[foo] = "blah";
I'm going to be getting an array of objects and want to set instance variables inside of a class based on a property. So if I get this:
ary = [{type: 'walrus', name: 'GorbyPuff'}, {type: 'humanoid', occupation: 'KingSlayer'}]
I want to initialize an object where #walrus == ary[0] and #humanoid == ary[1]
In Ruby I could user instance_variable_set, but how can this be accomplished in the Javascripts?
I'm not sure if I get what you're trying to acchieve, but the easiest way to do this would be:
var theObj = {};
for(var i=0;i<ary.length;i++)
{
theObj[ary[i].type] = ary[i];
}
The worry here is, that by altering the ary variable you will inadvertently alter the theObj:
console.log(theObj.walrus.name);//Outputs: GorbyPuff
ary[0].name = 'Nips!';
console.log(theObj.walrus.name);//Outputs: Nips! <-- objects are passed by reference, always
If the ary variable is part of a function scope, and the resulting object is its return value, you needn't worry. But if both are part of the global scope (Which they shouldn't, it's bad practice), this becomes an issue.
I therefore propose this approach:
var obj = {};
var i;
while (ary.length !== 0)
{
i = ary.splice(0,1)[0];//removes element from array
if (i.hasOwnProperty('type'))//always best to check the property you're going to use is there
{
obj[i.type] = i;
}
}
There's nothing in JS that can do this for you, just do a loop to build the object you want:
ary = [{type: 'walrus', name: 'GorbyPuff'}, {type: 'humanoid', occupation: 'KingSlayer'}]
instances={}
for(x=0;x<ary.length;x++) instances[ary[x].type]=ary[x]
document.write(instances.walrus.name) //GorbyBuff
document.write(instances.humanoid.occupation) //KingSlayer
If you want to use that array of objects as prototypes, you can do this:
var Walrus = function(){};
Walrus.prototype=ary[0];
var aWalrus = new Walrus(); // creates a new Walrus. aWalrus.name => GorbyPuff
In Javascript the Good Parts, Douglas Crawford describes a more general way of doing it:
if (typeof Object.create !== 'function') {
Object.create = function (o) {
var F = function () {};
F.prototype = o;
return new F();
};
}
Which you can use like this:
var aWalrus = Object.create(ary[0]);
here is a example of what you want:
// the class:
function MyClass(){
// stuff
}
// the data object
var o = [
{type:"MyClass",name:"a name"}
]
// how to instantiate:
var instances = [];
for(var i=0;i<o.length;i++){
if(typeof this[o[i].type] == "function")
instances.push(new this[o[i].type](o[i].name))
}
If you create the classes in a function you need to use "this" as a reference to that function, else you can use "window"