Frage

I execute some function and get a return value. This value could be anything (string, array, object, reference, function). I then pass this result along using JSON.stringify.

Now, the functions and references don't do me much good in the scope they're being delivered to, so the whole "to string, eval" method isn't much use. I'm going to store them in a local array and just pass along an ID to reference them by later. But, I do go ahead and send string data, arrays, and objects (in the "associated array" sense of javascript objects) as those all play very nicely with JSON.stringify.

I'm already using try... JSON.stringify() catch to do this with recursive objects (which JSON.stringify errors on.) But that doesn't account for anything else mentioned above.

What is the most efficient way to check if an value contains a function?

And not

typeof foo === "function"

Because the return might be

["foo", "bar", ["foo", "bar"], function(){...something}]

I don't want to pick apart each individual piece's type either, just return on the whole whether there's ANY functions/objects that cannot be safely stringified. I could probably work out how to loop and check each individual value, but if there's a shortcut or more efficient method someone can think of, I'd like to hear it.

Thanks!

War es hilfreich?

Lösung

Refining welcome and appreciated!

//your favorite object length checking function could go here
$.objectLength = (function(){
    //ie<9
    if (typeof Object.keys === "undefined" ){
        return function(o){
            var count = 0, i;
            for (i in o) {
                if (o.hasOwnProperty(i)) {
                    count++;
                }
            }
            return count;
        };

        //everyone else
    } else {
        return function(o){
            return Object.keys(o).length;
        }
    }
})();

//comparing our two objects
$.checkMatch = function(a, b){

    //if they're not the same length, we're done here. (functions exist, etc)
    if (typeof a !== typeof b || typeof a === "object" && typeof b === "object" && a && b && $.objectLength(a) !== $.objectLength(b)){
        return false;

    //if they are the same length, they may contain deeper objects we need to check.
    } else {
        var key;
        for (key in a){

            //make sure it's not prototyped key
            if (a.hasOwnProperty(key)){

                //if it doesn't exist on the other object
                if (!b.hasOwnProperty(key)){
                    return false;

                //if this an object as well
                } else if (typeof a[key] === "object"){

                    //check for a match
                    if (!$.checkMatch(a[key], b[key])){
                        return false;
                    }

                //then check if they're not equal (simple values)
                } else if (a[key] !== b[key]){
                    return false
                }
            }
        }
        return true;
    }
};
//...stuff

//catch recursive objects in parameters
var good = true, sendObject = {"ourobject", "values"}, finalSendObject;
//try to stringify, which rejects infinitely recursive objects
try {
    finalSendObject = JSON.stringify(sendObject);
} catch(e){
    good = false;
}
//if that passes, try matching the original against the parsed JSON string
if (good && sendObject !== JSON.parse(finalSendObject)){
    good = $.checkMatch(sendObject, JSON.parse(finalSendObject));
}

Andere Tipps

This will not work

But I will leave it up for anyone who thinks of trying it. Working solution coming shortly.

30 seconds later, I figure it out myself.

String it, parse it. If anything changed, it wont be equal to itself.

var checkParse = function(obj){
    return obj === JSON.parse(JSON.strigify(obj));
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top