I have a simple object called Entry, which until just recently only had a few basic properties. During certain events, I would perform REST actions on these objects to an API living in C# code. Until just recently, this worked fine. I would POST or PUT these objects in the body of an AJAX request using my little request service, which ended like so:
$.ajax(url,
{
type:method,
headers:headers,
data:options.data, //there is an instance of Entry in options.data
timeout: this.timeoutLength
});
Recently I added a function to the Entry.
function Entry(foo, bar){
this.foo = foo;
this.bar = bar;
this.doStuff = function(){ ... } //added this code
}
I added the function, but questioned the user story behind its use again so I switched back to the browser, refreshed, and ran some more tests. Without ever calling the function doStuff anywhere, it’s effects were being seen.
I replaced doStuff‘s body with a simple alert, and sure enough every time I did something that behind the scenes called an AJAX request with an Entry object, I got my alert message. Why in the world is this happening? Why is doStuff being called without me telling it to?
Edit: tldr; Ajax calls any functions in an object when serializing it. If you care why, read on:
This drove me a little crazy, until I managed to follow the stack trace backwards. It seems the function
doStuffwas being called by jquery-1.7.1.js$.ajax. But why?The object in question, "entry" here, has to be serialized into a query string for sending over the network. In doing so, it goes through each of the object’s properties.
First, (on line 7610 for me) it checks if the object
isPlainObject. It may have been before, but having a function no longer makes it so. Instead, it does the following:It defined add just a little earlier, as so:
Note the comment jQuery lovingly provided us. It goes through every property of the object, and if one is a function it uses the function’s return value as the "value" of the "key/value" pair. It was calling
doStuffhere to get a value (which of course returnedundefinedbecause the function simply called an alert)I will add, for my own sake, that the documentation doesn’t really make this explicit. I always assumed it ignored functions, but its good to not that it most certainly does not.
Finally, through a simple test (not full reading the code), it seems that
JSON.stringifydoes ignore functions altogether.