5

I came across an odd occurrence today while troubleshooting a rogue AJAX request in our application. We send data back to the server, using jQuery.param to build the request string.

In one scenario, the object fed to the param function had a null option, so it looked something like this:

var myData = {
     x : 1,
     y : null
};
var params = jQuery.param(myData);

This code is actually buried in a backbone collection, but the principle is the same.

Now, I was completely shocked when the parameter, when received by the server, for the variable y was the literal string "null", rather than being null.

After some digging, I found that encodeURIComponent(null) returns the string "null" and more interestingly '' + null yields "null" as well. This was tested on Chrome 23, as well as Firefox 11.

The object ultimately being sent to the jQuery.param function gets built from arguments to a function, and null is a completely valid value for the parameter. I got around it by just building the object with y : param || '', but I'm curious as to the apparent wrongness of the native JS function, as well as why '' + null = "null", since they are generally regarded as two different concepts.

Thomas Jones
  • 4,892
  • 26
  • 34
  • 5
    http://stackoverflow.com/a/10362142/362536 – Brad Dec 10 '12 at 21:13
  • Thanks @Brad. This didn't show up in any of my searches. Interesting example of the programming behind it, though I guess the decision had to be made somewhere when doing type conversion – Thomas Jones Dec 10 '12 at 21:15
  • I would consider that a bug in `jQuery.param`. `{foo: 'bar'}` should turn into `?foo=bar`, `{foo: ''}` should turn into `?foo=` and `{foo: null}` should turn into `?foo`. – zzzzBov Dec 10 '12 at 21:15
  • @zzzzBov: It's not a bug as long as jQuery's documentation doesn't claim that that is the expected behaviour, which is doesn't. – Lightness Races in Orbit Dec 10 '12 at 21:17
  • jQuery.param uses encodeURIComponent behind the scenes. I agree that it should check for the variable to be null before running it through, but the real "bug" is in encodeURIComponent imo. – Thomas Jones Dec 10 '12 at 21:17
  • 2
    If you're going to say there's a bug here (which is debatable imho), then the bug is in the EcmaScript spec that says `null` becomes "null" when cast to a string. – broofa Dec 10 '12 at 21:20
  • 1
    Thanks @broofa. For those wondering, the relevant section is here http://www.ecma-international.org/ecma-262/5.1/#sec-9.8 – Thomas Jones Dec 10 '12 at 21:23
  • 1
    `encodeURIComponent` works as defined, which assumes a string input and produces string output. Casting `null` to a string in JavaScript does exactly as is defined, which is not intuitive, but necessary for historical reasons. jQuery, on the other hand, is not well defined for `null` and `undefined` as input values, as it implicitly assumes string input for all keys. To that effect @LightnessRacesinOrbit is correct in that the behavior isn't expected, but I still consider it to be a bug given how query strings work. – zzzzBov Dec 10 '12 at 21:34
  • @zzzzBov jQuery apparently fixed this behavior in 1.8 http://bugs.jquery.com/ticket/8653 It "correctly" would output "x=1&y=" from jQuery.param – Thomas Jones Dec 11 '12 at 17:42

1 Answers1

3

The overloaded + operator attempts to convert both operands to a common type before performing its operation. If either operand is a string, it converts both operands to a string and then performs string concatenation.

See the ecmascript definition for the behavior of the + operator:

If Type(lprim) is String or Type(rprim) is String, then Return the String that is the result of concatenating ToString(lprim) followed by ToString(rprim)

jbabey
  • 45,965
  • 12
  • 71
  • 94
  • is that why encodeURIComponent works the same way? Its implicitly joining strings at the end of it? – Thomas Jones Dec 10 '12 at 21:16
  • and I knew that type conversion took place, I just wasnt expecting `null` to be converted to `"null"` when that took place – Thomas Jones Dec 10 '12 at 21:18
  • 2
    The EcmaScript spec (section 15.1.3.4) specifies that the first thing encodeURIComponent() does is cast it's argument to a string. Hence `null` becomes "null" – broofa Dec 10 '12 at 21:23