How can I serialize a function in JavaScript?

javascript serialize
serialize javascript function
javascript serialize object
jquery serialize form to json
serialization and deserialization in javascript
json serialize javascript
node serialize javascript
jquery ajax serialize form data example

For example, say I have a function defined as follows:

function foo() {
  return "Hello, serialized world!";
}

I want to be able to serialize that function and store it using localStorage. How can I go about doing that?

Most browsers (Chrome, Safari, Firefox, possibly others) return the definition of functions from the .toString() method:

> function foo() { return 42; }
> foo.toString()
"function foo() { return 42; }"

Just be careful because native functions won't serialize properly. For example:

> alert.toString()
"function alert() { [native code] }"

Serializing object methods using ES6 template strings and eval, JSON (JavaScript Object Notation) is a lightweight data-interchange format. […] JSON is a text Object serialization and the replacer function. JavaScript JSON Serialization: toJSON() Method. Other than JSON.stringify(), sometimes objects need custom JSON serialization, for that purpose the method toJSON() to return the proper JSON representation. The method toJSON() can be used on any object to return a serialization value. Example: JavaScript JSON Serialization: toJSON() Method.

function foo() {
  alert('native function');
  return 'Hello, serialised world!';
}
Serializing
var storedFunction = foo.toString();
Deserializing
var actualFunction = new Function('return ' + foo.toString())()
Explanation

foo.toString() will be string version of the function foo

"function foo() { ... return 'Hello, serialised world!';}"

But new Function takes the body of a function and not the function itself.

See MDN: Function

So we can create a function that returns us back this function and assign it to some variable.

"return function foo() { ... return 'Hello, serialised world!';}"

So now when we pass this string to the constructor we get a function and we immediately execute it to get back our original function. :)

Serializing / deserializing JavaScript functions *with free variables , Serializing / deserializing JavaScript functions *with free variables*. serialize- function.js. var a = 123, b = 'hello';. function test(x, y) {. console.log(this);. return a +� Form data can be serialized by both jQuery and JavaScript but, the major difference between them is that, jQuery’s serialize () method returns form field values in top down sequence whereas, serialize JavaScript returns it in bottom up sequence.

I made this answer to address some pretty big flaws with the existing answers: .toString()/eval() and new Function() on their own wont work at all if your function uses this or named arguments (function (named, arg) {}), respectively.

Using toJSON() below, all you need to do is call JSON.stringify() as usual on the function, and use Function.deserialise when parse()ing.

The following wont work for concise functions (hello => 'there'), but for standard ES5 fat functions it'll return it as it was defined, closures notwithstanding of course. My other answer will work with all that ES6 goodness.


Function.prototype.toJSON = function() {
    var parts = this
        .toString()
        .match(/^\s*function[^(]*\(([^)]*)\)\s*{(.*)}\s*$/)
    ;
    if (parts == null)
        throw 'Function form not supported';

    return [
        'window.Function',
        parts[1].trim().split(/\s*,\s*/),
        parts[2]
    ];
};
Function.deserialise = function(key, data) {
    return (data instanceof Array && data[0] == 'window.Function') ?
        new (Function.bind.apply(Function, [Function].concat(data[1], [data[2]]))) :
        data
    ;
};

Take a look at the DEMO

At it's simplest:

var test = function(where) { return 'hello ' + where; };
test = JSON.parse(JSON.stringify(test), Function.deserialise);
console.log(test('there'));
//prints 'hello there'

More usefully, you can serialise entire objects containing functions and pull them back out:

test = {
  a : 2,
  run : function(x, y, z) { return this.a + x + y + z; }
};
var serialised = JSON.stringify(test);
console.log(serialised);
console.log(typeof serialised);

var tester = JSON.parse(serialised, Function.deserialise);
console.log(tester.run(3, 4, 5));

Outputs:

{"a":2,"run":["window.Function",["x","y","z"]," return this.a + x + y + z; "]}
string
14

I didn't test older IE's, but it works on IE11, FF, Chrome, Edge.

NB, the name of the function is lost, if you use that property then there's nothing you can do, really. You can change it to not use prototype easily, but that's for you to do if that's what you need.

jQuery serialize() Method, Well organized and easy to understand Web building tutorials with lots of examples of how to use HTML, CSS, JavaScript, SQL, PHP, Python, Bootstrap, Java� How to serialize a JavaScript array? Javascript Web Development Front End Technology The serializeArray () method serializes all forms and forms elements like the.serialize () method but returns a JSON data structure for you to work with. Let’s say the following is the content in PHP file serialize.php −

If you needed a way to serialise Arrow Functions in ES6 I have written a serialiser that makes everything work.

All you need to do is call JSON.stringify() as usual on the function or object containing the function, and call Function.deserialise on the other side for the magic to work.

Obviously you shouldn't expect closures to work, it is serialisation after all, but defaults, destructuring, this, arguments, class member functions, it'll all be preserved. If you're only using ES5 notations please just use my other answer. This one really is above and beyond


Here's the demonstration

Working in Chrome/Firefox/Edge. Bellow is the output from the demo; a few functions, the serialised string, then calling the new function created after deserialisation.

test = {
    //make the function
    run : function name(x, y, z) { return this.a + x + y + z; },
    a : 2
};
//serialise it, see what it looks like
test = JSON.stringify(test) //{"run":["window.Function",["x","y","z"],"return this.a + x + y + z;"],"a":2}
test = JSON.parse(test, Function.deserialise)
//see if `this` worked, should be 2+3+4+5 : 14
test.run(3, 4, 5) //14

test = () => 7
test = JSON.stringify(test) //["window.Function",[""],"return 7"]
JSON.parse(test, Function.deserialise)() //7

test = material => material.length
test = JSON.stringify(test) //["window.Function",["material"],"return material.length"]
JSON.parse(test, Function.deserialise)([1, 2, 3]) //3

test = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c
test = JSON.stringify(test) //["window.Function",["[a, b] = [1, 2]","{ x: c } = { x: a + b }"],"return a + b + c"]
JSON.parse(test, Function.deserialise)([3, 4]) //14

class Bob {
    constructor(bob) { this.bob = bob; }
    //a fat function with no `function` keyword!!
    test() { return this.bob; }
    toJSON() { return {bob:this.bob, test:this.test} }
}
test = new Bob(7);
test.test(); //7
test = JSON.stringify(test); //{"bob":7,"test":["window.Function",[""],"return this.bob;"]}
test = JSON.parse(test, Function.deserialise);
test.test(); //7

And finally, the magic

Function.deserialise = function(key, data) {
    return (data instanceof Array && data[0] == 'window.Function') ?
        new (Function.bind.apply(Function, [Function].concat(data[1], [data[2]]))) :
        data
    ;
};
Function.prototype.toJSON = function() {
    var whitespace = /\s/;
    var pair = /\(\)|\[\]|\{\}/;

    var args = new Array();
    var string = this.toString();

    var fat = (new RegExp(
        '^\s*(' +
        ((this.name) ? this.name + '|' : '') +
        'function' +
        ')[^)]*\\('
    )).test(string);

    var state = 'start';
    var depth = new Array(); 
    var tmp;

    for (var index = 0; index < string.length; ++index) {
        var ch = string[index];

        switch (state) {
        case 'start':
            if (whitespace.test(ch) || (fat && ch != '('))
                continue;

            if (ch == '(') {
                state = 'arg';
                tmp = index + 1;
            }
            else {
                state = 'singleArg';
                tmp = index;
            }
            break;

        case 'arg':
        case 'singleArg':
            var escaped = depth.length > 0 && depth[depth.length - 1] == '\\';
            if (escaped) {
                depth.pop();
                continue;
            }
            if (whitespace.test(ch))
                continue;

            switch (ch) {
            case '\\':
                depth.push(ch);
                break;

            case ']':
            case '}':
            case ')':
                if (depth.length > 0) {
                    if (pair.test(depth[depth.length - 1] + ch))
                        depth.pop();
                    continue;
                }
                if (state == 'singleArg')
                    throw '';
                args.push(string.substring(tmp, index).trim());
                state = (fat) ? 'body' : 'arrow';
                break;

            case ',':
                if (depth.length > 0)
                    continue;
                if (state == 'singleArg')
                    throw '';
                args.push(string.substring(tmp, index).trim());
                tmp = index + 1;
                break;

            case '>':
                if (depth.length > 0)
                    continue;
                if (string[index - 1] != '=')
                    continue;
                if (state == 'arg')
                    throw '';
                args.push(string.substring(tmp, index - 1).trim());
                state = 'body';
                break;

            case '{':
            case '[':
            case '(':
                if (
                    depth.length < 1 ||
                    !(depth[depth.length - 1] == '"' || depth[depth.length - 1] == '\'')
                )
                    depth.push(ch);
                break;

            case '"':
                if (depth.length < 1)
                    depth.push(ch);
                else if (depth[depth.length - 1] == '"')
                    depth.pop();
                break;
            case '\'':
                if (depth.length < 1)
                    depth.push(ch);
                else if (depth[depth.length - 1] == '\'')
                    depth.pop();
                break;
            }
            break;

        case 'arrow':
            if (whitespace.test(ch))
                continue;
            if (ch != '=')
                throw '';
            if (string[++index] != '>')
                throw '';
            state = 'body';
            break;

        case 'body':
            if (whitespace.test(ch))
                continue;
            string = string.substring(index);

            if (ch == '{')
                string = string.replace(/^{\s*(.*)\s*}\s*$/, '$1');
            else
                string = 'return ' + string.trim();

            index = string.length;
            break;

        default:
            throw '';
        }
    }

    return ['window.Function', args, string];
};

.serialize(), The .serialize() method creates a text string in standard URL-encoded notation. It can act <script src="https://code.jquery.com/jquery-3.5.0.js"></script>. </head>. The above code brings the inserted DB id for each record and on each row in the above table an select option from wich the user can chose some value. When user finishes, he will press the button " Finish transfers" and all the inputs must be serialized.

Being a bit annoyed with the shortcomings of JSON i wrote a little serialize function that correctly handles serializing: functions, null, undefined, NaN and Infinity. Only thing it doesn't do it serialize class instances, since I couldn't think of a way to get around calling the constructor again.

let serialize = function(input){
    const escape_sequences = {"\\\\": "\\\\", "`": "\\`", "\\\\b": "\\\\b", '"': '\\"', "\\n": "\\n", "\\\\f": "\\\\f", "\\r": "\\r", "\\\\t": "\\\\\\t", "\\\\v": "\\\\v"};
    if(typeof input === "string"){
        let result = input;
        for(var key in escape_sequences){
          result = result.replace(new RegExp(key, "g"), escape_sequences[key]);
        }
        return '`'+result+'`';
    }else if(typeof input === "number"){
        return input.toString();
    }else if(typeof input === "function"){
        // Handle build in functions
        if((/\{\s*\[native code\]\s*\}/).test('' + input)) return input.name;
        return input.toString().replace(/"/g, '\"');
    }else if(typeof input === "symbol"){
        return input.toString();
    }else if(input === null || input === undefined){
        return input;
    }else if(input instanceof Array){
        let res_list = [];
        for(let i = 0; i < input.length; i++){
            res_list.push(serialize(input[i]));
        }
        return "["+res_list.join(",")+"]";
    }else if(input.constructor == Object){
        let res_list = [];
        for(let key in input){
            res_list.push('"'+key.replace(/"/g, '\\"')+'":'+serialize(input[key]));
        }   
        return "{"+res_list.join(",")+"}";
    }else if(typeof input === "object"){
        throw(`You are trying to serialize an instance of `+input.constructor.name+`, we don't serialize class instances for a bunch of reasons.`)
    }else{
        return input;
    }
}

let unserialize = function(input){
    return Function(`
        "use strict";
        return `+input+`;`
    )();
}

Lets test it!

let input = {
    'a': "str normal",
    'b"': 'str "quote"',
    'c': 1,
    'd': -1.3,
    'e': NaN,
    'f': -Infinity,
    'g': ()=>123,
    'h': function(){return "lalala"},
    'i': null,
    'j': undefined,
    'k': true,
    'l': Symbol(123),
    'm': [1,2,3],
    'n': [{"a": "str normal",'b"': 'str "quote"','c': 1,'d': -1.3,'e': NaN,'f': -Infinity,'g': ()=>123,'h': function(){return "lalala"},'i': null,'j': undefined,'k': true,'l': Symbol(123),'m': [1,2,3],}],
};

let output = unserialize(serialize(input));

for(let key in input){
    console.log(input[key], output[key]);
}

Serialization, In JavaScript, for example, you can serialize an object to a JSON string by calling the function JSON.stringify() . CSS values are serialized by� javascript - serialize - how to convert html form field values to a json object Easy To Use Function. I Have Created A Function For This. function FormDataToJSON

serialize-javascript, Serialize JavaScript to a superset of JSON that includes regular expressions and functions. The serialize() function accepts a single parameter which is the data we want to serialize and returns a serialized string. Syntax: serialize( $values_in_form_of_array )

Serializing JavaScript Functions, Use Pulumi's Node.js SDK to serialize JavaScript functions into an artifact that can be used at runtime in the cloud. Given a JavaScript Object and the task is to serialize it into a URL query parameters using JavaScript. Approach 1: Declare an object and store it into the variable. Then use JSON.stringify() method to convert javascript object into string and display the content.

What is a best / simplest way to serialize / deserialize JavaScript , function serialize (obj: any) { return JSON.stringify( obj, (_, v) => v instanceof Date ? { __date__: +v } : v ) } function deserialize (s: string) { return� An empty field is still considered to be data. There are two options. Manually pre-process the data destined to be serialized and remove the empty fields yourself, with the delete method, or

Comments
  • why do you want to serialize a function?
  • What if the function being serialised references variables/functions in the containing scope? If you deserialise it in the wrong place it won't work...
  • Can't speak to Akash's use, but I want to serialize a function to store it as a validation function in CouchDB. The variables passed in and restricted scope are well defined.
  • @DanielA.White It really irritates me when this is the first response to somebody's question!
  • People blow off questions they consider bad practice all too often on StackOverflow instead of just objectively answering the question and then adding a word of advice afterwards. The latter is much more helpful to beginners.
  • How would you get the function back from the string?
  • @David Wolever - the ES 3 and 5 specs say that Function.prototype.toString returns "[an] implementation-dependent representation of the function" that "has the syntax of a FunctionDeclaration" (§15.3.4.2). Probably worth noting that there is nothing to say that it must be the literal code of the function, it could just be function foo(){/* returns 42 */}.
  • You might want to note that this won't easily work if the function is a closure.
  • @AkashGupta use Function's constructor with return statement
  • I have made a much simpler version here, but the tradeoff is that your function gets reconstructed for every call to the deserialised one. This should be negligible, so use this if you're not fond of the huge arguments parser above
  • What you have done here is very ill-advised, you've made many more "shortcomings" than you've resolved; don't replace JSON, add to it. I've written streaming JSON writers and parsers and there is much more to the format than you seem to know. For example, serialize('\\'), you output "\"; broken. Sure you could fix that, but I'm telling you, it's fundamentally all broken (not to mention inefficient).
  • Unfortunately, you can't replace Number.prototype.toJSON() for some reason, so your only bet is to roll your own Number wrapper. I have usefully included a demonstration of the fact that null is already supported natively (one of your purported annoying limitations) and that you don't need to use `this` + variable + `that`, you can just do `this${variable}that`
  • It's not a style thing, it's one of the only reasons to use backticks. Otherwise just stick to "this" + variable + "that". I fail to see how switching between " and ` on a whim is your idea of okay practice, almost like haphazardly flicking between spaces and tabs. You don't need to agree, but string additions instead of buffers, multiple regexs instead of proper escape sequencing: it's objectively inefficient and error-prone. If it happens to work for you, fine, you do you, but I comment for posterity, not necessarily in reply to the OPs; for others on SO to read, not necessarily you.
  • The point is, if you didn't know, or don't care for the difference in those details, nothing you write up in 30minutes will be good enough to replace an in-built library that is the backbone for so many things, and shouldn't be recommended to people all over the internet. Case in point the changes you made made it worse, outputting {'\\u70':'wrong'} as {"\u70":`wrong`} instead of {"\\u70":"wrong"}. You haven't read the standard, and you really need to to implement something like this if you expect it to be able to interface with anything.
  • While this code may answer the question, providing additional context regarding how and why it solves the problem would improve the answer's long-term value.