I have an object that contains arrays which is made up of other arrays it also contains methods. The problem that i am facing is that i can't use JSon because of the multidimensional arrays and the methods.
The reason i want to convert it to a string is to store into the Iphone's
localStorage.
you can only store text inside of there and i was hoping for a way to store a complex object about a user as a string and able to deserialize it again after. Is there even a way to do this. I don't know javascript well enough to write my own api. That was the option i started to try and look into at this point :(
Serialize it to JSON. You can serialize / deserialize complex objects and arrays.
There is no way you can serialize methods (code).
For local storage persistence I would recommend Lawnchair.
no need to store in localStorage you can use global array any where in your application try this once
It's normally possible to serialise a method using myfunc.toString()
So, you could use a replacer function in JSON.stringify() and JSON.parse() to recognise methods, and call .toString() on them, and them somehow recognise them on parsing and turn them back into first class functions.
However - note that a reconstructed function will not have access to the original object's scope, i.e. private variables, or methods, etc.
e.g.
function A() {
var foo = 'bar';
this.test = function test() { console.log(foo) };
};
var b = new A();
var f = b.test.toString(); // the text of the method
b.test2 = new Function(f);
b.test2();
> undefined
well,
there is a way to convert object with functions to string and vise verse. take a look at this plugin:
http://www.eslinstructor.net/jsonfn/
good luck,
-Vadim
Related
From the MDN documentation:
reviver (Optional)
If a function, prescribes how the value originally produced by parsing is transformed, before being returned.
Its name strikes me as odd. Maybe I’m missing a metaphor here — why would this be called “reviving” an object? Is there any history to such a transformer function being called a “reviver”? Googling reviver +javascript shows that JSON.parse is basically the only place where this term is used.
The idea is that native Javascript objects, like a Number(42), are your "live" objects. When you serialise those into a JSON representation, they're "dried up", or "dumbed down", or whatever you want to call it. To get your fresh live Javascript objects back, you need to "revive" them from their simple text representation.
This becomes more apparent if you use more complex objects:
function Foo(bar) {
this.bar = bar;
}
Foo.prototype.baz = function () {
alert(this.bar);
};
var f = Foo(42);
f.baz();
f = JSON.parse(JSON.stringify(f));
f.baz(); // Nope
To get the original object back which has a baz method, you need to do a little more than just parse it. That's the "reviving" part.
The parse function is used to create an object from data that has been serialized into a string. By default, all it can do is reconstitute the data into plain objects with a bunch of properties.
Sometimes, you may want to "bring these values back to life" (i.e. revive them) into full-fledged objects with methods, behaviors, etc., or even objects that have a particular type, instead of just the lifeless containers of values that JSON.parse() produces by default.
I would say that's why it's called a reviver.
For example I have class:
function Test() {
}
Test.prototype = {
'setTest' : function(test) {
this.test = test;
}
}
var test = new Test();
Test.setTest('test');
I want to save object test in database.
How to serialize object test to string? (methods, variables, etc)
Simple with json
JSON.stringify( test );
In this case, for the question you're asking, there really isn't a way to do what you want. The problem with your request lies in "serializing everything attached to the object, including functions".
Serialization normally only occurs for data, because executables are usually machine bound, in that they are compiled for a given machine, based on certain characteristics. Now, it's reasonable to say that javascript functions just require a javascript interpreter, because javascript is write-once, run-everywhere. But when people write serializers, because all serializers tend to work the same, we write them for data only. In this case, the industry standard is JSON, which is an object-data only serializer.
There are three solutions that avail themselves to you at this point:
Write your own serialier/deserializer that encapsulates functions. This can be tricky, because not all javascript engines will give you access to the source.
Write your own re-loading mechanism that generates a specific new initialized type on each restore, and save the typename as one of the properties on serialization. That way the initialization of each variable gives you the methods, and then merging with the data gives you the complete object.
Store each function as a string and eval it on the fly as you need it. This is incredibly tricky, and is quite prone to errors. I can think of no case where this becomes helpful, because it's quite fragile. However, it is an option, and cannot be overlooked.
I know that 3 is a sub-answer for 1, so you can consider it that there are only two useful answers.
I know that superficially this works on Chrome and IE9, so it should work everywhere the majority of users are likely to use it:
var abc = function(thing) { return thing; }
abc.toString();
// gives "function(thing) { return thing; }" on the command line
So you can certainly serialize the methods as strings in place of the actual method, but you're going to need to create a duplicate object so you can capture every element on the source object (I think, rather than replacing them in place).
Hopefully this helps you think about the problem some more, and maybe to realize you don't need to serialize the methods (nobody ever does that I know of, not reasonably).
The best way to do this is to write your own serialize method which creates a JSON object with attributes, based on your getters. Normally you define a getter per attribute. So it should work for most cases (so you don't have to define a serialize method for each class).
function serialize(obj) {
var serialized = {};
for(var prop in obj) {
if (obj.hasOwnProperty(prop) && typeof obj[prop] == 'function') {
if (/^get.*/.test(prop)) {
var value = obj[prop]();
var name = prop.replace('get', '');
if (typeof value === 'object') {
serialized[name] = this.serialize(value);
continue;
}
serialized[name] = value;
}
}
}
return serialized;
};
To reset your attribute values back to the class you have two options:
Create a function in your class which creates a valid object instance based on the serialized JSON.
Create a unserialize method and map the JSON with your class using the setters.
Example:
function unserialize(obj, emptyClass) {
// Check emptyClass for setters and map the data from obj to it.
return 'class instance';
}
Typically, you'd do this with JSON, which is widely supported across browsers/languages/libraries/etc. The only hangup is that JSON does not support functions – but do you really need to serialize those?
I've had to support functionality similar to this before. I ended up saving the name of the function as a string and serializing it as JSON. Then when I come back to the client, I execute the function using a helper like the one posted in this question.
If anyone has a better way to solve this problem, I'd want to see it!
I recently had to find a solution for this problem. I'm sure it can be improved upon.
First I created a module for instantiating the "serialisable" object.
function MyObj(serialised){
this.val = "";
if(serialised){
var unserialised = JSON.parse(serialised);
for (var i in unserialised) {
this[i] = unserialised[i];
}
}
}
MyObj.prototype.myMethod = function () { return this.val;};
module.exports = MyObj;
you of course have to consider error handling and other validations.
I have a JavaScript array that contains 150 JavaScript functions (these functions return financial indicators). when i load my page, i have this array. I'm wondering is it possible to use these loaded functions on that page?
I've converted my array to string and picture below shows how it looks like in alert mode:
arry alert mode http://bsl.site40.net/pic/8cdf49ea54ee.jpg
In above picture the (faunction a, b, c) are where my functions take place and there is 150 functions (the string {"itemCode":___}, will be repated each time i ad a function). I think there should be some string replace and then inserting the functions on that page in someway. mmm i don't know. can you help me?
I have another question: is it possible for a javascript array to be very long (for example 20000 characters)?
Edit: my array has complete code of functions. in that picture i showed only their name in order to picture be viewable
I would suggest you use a json object instead of an array, it will be easier to look up.
If you keep using an array you will have to loop over the array in order to find the correct functionname/function.
If your json object holds function names that are declared globally you can call them like this
var functionName = "myFunc";
window[functionName]();
But you probably should not declare your functions globally but store them in some sort of namespace.
If your json object contains the actual function ( and i would recommend this ), you can call it with
var functionName = "myFunc";
myObject[functionName]();
If your object contains the function code as a string, you will have to eval it to execute it. Your function will need to be wrapped in parentheses, i would not suggest this method !
You would be even better off to dynamically load the functions with some sort of jsonp.
var functionName = "myFunc";
var myFunc = eval('(' + myObject[functionName] + ')');
myFunc();
An array can contain a maximum of 4,294,967,296 elements, but you will have obliterated your performance long before you reach that, i'm not so sure about json objects tough.
You can use the function eval(string) if the functions are stored as strings. This is not recommended though. If they are stored as objects using parenthesis like this (functionName) will be enough.
I have a json object with a function:
var thread = {
title: "my title",
delete: function() {
alert("deleted");
}
};
thread.delete(); // alerted "deleted"
thread_json = JSON.encode(thread); // convert to json from object
thread_object = JSON.decode(thread_json); // convert to object from json
thread_object.delete(); // this didn't work
After I converted it back from json string to object, I could not use delete() function.
When you convert something to json, the functions are gone?
Are there ways to keep them in the json string?
I'm using Mootools.
You got it. Take a look at that JSON.encode output. Only simple data types are allowed in JSON representations, partly for ease of creation, and partly for security. (The reason we use something like JSON.decode instead of eval is the possibility of embedding functions.)
You'll have to modify the JSON library source code to accept functions, or write your own in order to preserve the literal definition of the object upon conversion to string.
Consider, though, the possibility that you don't really need to do this. There's probably a better solution, but I can't begin to address that without knowing your exact situation.
My JavaScript code stores a lot of data in arrays. I want to retrieve a key using something similar to what I wrote below. It key that should be retrieved is based on variables that are page-dependent . The following code doesn't work. Can anyone give me a solution to this problem?
This is part of a script that does automatic conjugation. (looks for SUBJECT in a div and then looks for VERB in another div and then conjugates the verb by retrieving the conjugated form from the array)
function getarray(Array,Key) {
return Array[Key];
}
Example of how it should work:
verb = innerhtmlfromdiv;
subject = innerhtmlfromotherdiv;
function getarray(Array,Key) {
return Array[Key]; }
conjugatedverb = getarray(verb,subject);
htmltextbox.value = conjugatedverb;
First off, what you want is an Object, not an Array. I'm guessing that you're new to javascript and your previous language was either PHP or PERL, and so you think what you're using is an "Associative Array".
The basics: There is no such thing as Associative arrays in Javascript. There is Objects, and a non-primitive subclass of Object called Array, which has some methods for dealing with Numericly named object properties, and a magic length property.
Since the keys you are dealing with are strings, not numbers, you have no use for Arrays.
Javascript Objects on the other hand are similar to an Associative array in php, or a hash in perl. (but they are not exactly the same thing).
As you have no doubt discovered, with an Object, you can use subscript notation to access certain properties, as in
verbs["go"] = "went";
this is equivilent to
verbs.go = "went";
a common mistake is to think that the dot notation is only used for objects, and the subscript notation for "associative arrays", because this is how it works in PHP. In javascript the two notations are interchangable. Since Arrays are a subclass of Object, the above examples work on them as well (but they don't use any special properties of Arrays).
As for your specific problem:
You need an object full of objects.
so for instance
var verbs = {
"do":{"Truck":"Drive","Blender":"Turn On","Bike":"Ride"},
"take":{"Money":"Steal","Julie":"Accompany","Lever":"Pull}
}
then your function would be:
function conjugate (verb, subject) {
return verbs[verb][subject];
}
and an example of its use would be
conjugate("do","Truck") // returns "Drive"
Try changing the parameter name Array to something else. Array is the name of a built-in function/object in javascript.
I don't quite get the point of the function. This is like writing:
function getValue(var) {return var}
Why not just get the value the normal way without wrapping it in a useless function:
conjugatedverb = verb[subject];
htmltextbox.value = conjugatedverb;
Also, your code doesn't make sense when you claim to do an innerHTML from an element and somehow get an object instead of a string. What is really going on? I think your problem starts even before this snippet of code.