How to serialize an object in JavaScript? - javascript

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.

Related

running code in another function's scope (JavaScript)

So I'm working on a sort of JavaScript framework, just some utility things for myself to use in future projects, and I want to make a data binding system.
The first method I used was objects, and the code would just loop through the specified html element and look for occurences of {{key}} in the markup and then look for that key in the object and replace it that way in the HTML.
For example, if you had <div>{{name}} is a cool guy</div> in the HTML and had {name:"joseph"} in the JS then the final product would be displayed on screen as 'joseph is a cool guy'.
However, I decided later to change my method and instead the framework would except a function. So instead of {name:"joseph"} you would give it function(){ var name = "joseph" }.
This obviously looks better and gives a lot better functionality.
I changed the processing function so instead of looking for the key/value pair to replace the {{key}}, it just uses eval on the variable to gets its value.
My problem lies here: How do I run my search/replace code INSIDE the scope of the function the user passes.
If the user defines variables within that function, their values will not be available anywhere else due to scope issues.
I've tried using Function.toString() to actually modify the source code of the function, but nothing's working and it's all very complicated.
(The issues are not due to the actual solution, I think that Function.toString() might work, but due to my implementation. I keep getting errors)
So... What is the best way to run arbitrary code in the scope of another function?
Critera:
Obviously, I can't modify the function because the user is passing it in. (you can't just tell me to add the search/replace code to the bottom of the function)
The variables must stay in the local scope of the function. (no cheating by using window.name = "joseph" or anything)
I am also aware of how terrible eval is so any suggestions as to get it to work are greatly appreciated. Thanks!
Code:
function process(html) {
var vars = html.match( /({{)[^{}]*(}})/g )
// vars = ['{{variable}}', '{{anotherVariable}}']
var names = vars.map( function(x){ return x.replace("{{", "").replace("}}", "") } )
// names = ['variable', 'anotherVariable]
obj = {}
for (var i = 0; i < names.length; i++) {
obj[names[i]] = eval(names[i])
}
for (var p in obj) {
html = html.replace(new RegExp('{{'+p+'}}','g'), obj[p]);
}
return html
}
You should go back to your first method with the object, it's much better. You can still pass a function, but the function should return an object:
function () {
return { name: 'joseph' }
}

How to find the interface of a function in Javascript?

For example; the function alert or writeln; how could I find which interface these functions come from programmatically within JavaScript?
Yes, like this:
if (typeof(yourFunction) !== "undefined") {
// do something, like call the function
}
You can easily check to see that a function is defined with typeof:
if (typeof(maybeFunction) === "function") {
// do something
}
On the other hand, it is not easy in general to know where a function is defined. Different browsers host their core functional implementations in different places, and furthermore it is incredibly easy to copy references to functions:
var myAlert = alert; // Now myAlert is a function,
// but where will you find a function myAlert() declaration? Nowhere...
So I think the proper answer to your question is, it's not possible (in general). You can use a debugger to find it on the fly, or a good text editor or grep tool to find it offline, but you won't be able to find it programatically.
If you want to "list an objects functions", you can do:
function listOwnMethods(obj) {
var ownMethods = [];
for (var p in obj) {
if (obj.hasOwnProperty(p) && typeof obj[p] == 'function') {
ownMethods.push(p);
}
}
return ownMethods;
}
However, this will not list the non–enumerable properties. If you want to also get enumerable inherited methods, remove the hasOwnProperty test.
Some versions of JavaScript also have getters and setters, so properties may behave like functions even though their Type is not "function". Finally, host objects can return anything they like when tested with typeof, so you may not be able to determine all (or even any) of a host object's methods that way.

Binding objects parsed from JSON to classes

I want to pull a tree structured set of objects from a web service represented with JSON
When I unpack that, I'll wind up with a structure which uses vanilla Javascript objects. What I'd like to be able to do is bind each node to a specific class, so that method calls become available on each node of the tree.
My solution, using jQuery .extend()
Here's a simplified example which illustrates the approach.
I might define a simple class using jQuery .extend() as follows...
MyNode= function() {
this.init();
}
$.extend(MyNode.prototype, {
init: function() {
// do initialization here
},
getName: function() {
return this.nodeName;
}
});
Now given a simple object like this
var tree={
nodeName:'frumious',
nodeType:'MyNode'
}
I can make the object appear to be an instance of the desired nodeType with
$.extend(tree, eval(tree.nodeType+'.prototype'));
Note that I want the object to declare the class name, so I've used eval to locate the appropriate prototype for that class. (Thanks to Rob W for suggesting window[tree.nodeType].prototype as a better alternative)
Now I can do things like alert(tree.getName());
Better ways?
I write StackOverflow questions and find the act of describing it in enough detail to avoid a downvote is enough for me to solve it myself. This was no exception, but I'd be interested to hear of any more elegant approaches to this problem. This solution gets the job done, but I can't help but feel there must be other approaches...
I'd get rid off eval, and use:
$.extend(tree, window[tree.nodeType].prototype);
If MyNode is a local, but known variable, add it to an object, for reference. Eg:
var collection = {};
collection['MyNode'] = MyNode;
$.extend(tree, collection[tree.nodeType].prototype);
Alternatively, if the structure of the JSON is solid, I recommend a custom JSON parser, which also allows you to validate properties prior addition.

How to get method name from JavaScript file

I have a JavaScript file with many methods defined in it. Is there any way to know how many methods are in that file & what are the names of methods?
Is there any way to know that how many methods are there in Java
Script & what is the names of method?
Read the source or the documentation (if there is any).
If you're looking for some kind of "list avaialble methods" function, there isn't one. Writing one would be the equivalent of writing a javascript parser and perhaps even compiler.
Good luck with that. :-)
While, in theory, you could try to find everything that matched the pattern:
function <name>(
You'd be missing out on a lot of other types of functions. See, Functions are really just objects in JavaScript. They can be assigned, shared, modified, and moved around. So, you'd also have to find these:
var <name> = function() {}
And these:
function returnFunc() {
return function() {...}
}
var <name> = returnFunc();
As well as these:
obj.member = new Function();
And a nearly infinite variety of similar function definitions.
So, the answer is, most likely you can't. Unless the code is extremely narrowly constructed.
The short answer is "no".
The long answer is that if the JS file is your JS file, i.e., you control the content, then there are several ways that you can structure the code that will let you obtain a count or list of function names. Obviously that won't help you with other people's code. Apologies if you already know all of this, but just in case you don't: it's generally a good idea to wrap all of your "library" functions up as properties of a single object, something like this:
var myFunctionLibrary = {
doSomething : function() {},
somethingElse : function() {},
nonFunctionProperty : "test",
// etc.
}
This creates a single global variable called myFunctionLibrary, which is an object with properties that are references to functions. (Note: there are several other ways to achieve a similar effect, ways that I prefer over this way, but this seems simplest for purposes of this explanation.) You then access the functions by saying:
myFunctionLibrary.doSomething();
// or
myFunctionLibrary["doSomething"]();
Because all of your functions are then contained in a specific object you can iterate over them like any other object:
var funcCount = 0;
var propCount = 0;
for (fn in myFunctionLibrary) {
if (typeof myFunctionLibrary[fn] === "function"){
funcCount++;
alert("Function name: " + fn);
} else {
propCount++;
}
}
alert("There are " + funcCount + " functions available, and "
+ propcount + " other properties.");
The main advantage, though, is that you don't have to worry about your functions potentially having the same names as functions in some other library that you want to use.
Write a program to load your file into Rhino, and then inspect the dictionaries and see what you have.

ADVANCED_OPTIMIZATION without renaming

I am writing a Google Chrome extension with the help of Google closure compiler.
I make heavy use of the message API to communicate between code that runs on different processes. Thats why my files need to be compiled separately. If I use advanced optimizations I also have to access properties with quoted strings in data I send with this message API. That works without a problem but it makes my code look ugly. But I like the dead code removal that comes with advanced optimizations.
I would like to be able to do dead code removal without the renaming that comes with advanced optimizations. Is this possible with the closure compiler?
It is not possible out of the box, You can however download the source and make the customization yourself in Java.
Yes, I agree. It is ugly to have to use obj["prop"] instead of obj.prop in all your code that deals with data being passed around just to use the Closure Compiler in Advanced mode.
One trick I have developed is to build a mapping object:
var mapping = {
field1: "field1",
field2: "field2"
:
};
This object, after compiling by the Closure Compiler, will have field names mangled (renamed) mapping to the original, unmangled names, e.g:
var a = {
b: "field1",
c: "field2"
:
};
Then before I send the data, I pass it through a function that clones the entire data structure, converting each mangled field name into the unmangled version in the new object before passing the new object out:
function cloneData(obj) {
var newobj = {};
foreach (var name in obj) {
if (!obj.hasOwnProperty(name)) continue;
var fullname = mapping[name] || name;
newobj[fullname] = obj[name];
}
return newobj;
}
For data received, do the reverse.
Without knowing how many you want to hold onto, you might look into the "Export Symbols You Want To Keep" section of the docs.

Categories