I discovered a peculiarity in JavaScript (or perhaps my browser's idea of it):
var s = "Hello, world";
function foo(arg)
{
console.log(arg);
console.log(this);
}
foo.call(s, s);
Running the above with Firebug console enabled, I get:
Hello, world
String { 0="H", 1="e", more...}
Why does the string automatically get turned into a weird object before becoming the this
passed to foo
?
The reason I call it a weird object is because jQuery chokes on it. For example:
$.each(["one", "two", "three"], function(i, x) {
$('<p></p>').text(x) .appendTo('body'); // Works
$('<p></p>').text(this).appendTo('body'); // Doesn't work
});
this
is coerced into an object, i.e. Object("test")
is internally called.
(function() {
return this;
}).call("test");
// returns same as `new String("test")` or `Object("test")`
if the method is a function in non-strict mode ... primitive values will be boxed*.
Note that using strict mode indeed does return the primitive value:
(function() {
"use strict";
return this;
}).call("test") === "test"; // true
* Boxing a value of a value allocates an object instance and copies the value into the new object.
When using foo.call(s1, s2)
, you're invoking function foo
, and setting the this
keyword to s1
. Since this
has to be an object (so, not a primitive value), it's converted to a String
object.
The individual characters of a string (created through s = "..."
or s = String("...")
) can be accessed through indexes, hence
String { 0="H", 1="e", more...}
function foo(arg)
{
console.log(arg); // passed as "Hello, world"
console.log(this); // passed as String("Hello, world")
console.log(this instanceof String); //True
}
var i=0, s = "Hello, world";
for(; i<s.length; i++){
console.log(i, s[i]);
}
/* Prints:
0 H
1 e
...
*/
*/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With