when string is not a string

A

Alex Shabanov

Curious javascript sample.

Consider the following code:

var s = "asd"
var f = function() { return typeof(this) }

An expression typeof(s) returns true (as it is expected), but
f.call(s) returns false!

To make matters worse consider the following snippet:

var s = "asd"
var f = function() { return this instanceof String }

An expression f.call(s) returns true, but (s instanceof String)
returns false!


The question is why call transforms this to an object? Is it made for
unification, e.g. to make this iterable using 'for (var i in this)'
loop?

It is also unclear why string literal in fact is not an instance of
String in ("asd" instanceof String) expression but it does a string
in call/apply method invokations.

I see this might be a kind of boxing/unboxing in .NET, but I see no
reason why language designers made such a choice.
 
T

Thomas 'PointedEars' Lahn

Alex said:
Curious javascript sample.

There is no "javascript": said:
Consider the following code:

var s = "asd"
var f = function() { return typeof(this) }

An expression typeof(s) returns true

No, it does not. The expression is supposed to evaluate to and actually
evaluates to "string" in JavaScript 1.8.2, but in this context it evaluates
to "object" in JavaScript 1.8.2. BTW, `typeof' is an operator, so you
should lose the parentheses.
(as it is expected),

Check your assumptions.
but f.call(s) returns false!

No, it does not. Because `this' always refers to an object, that call
returns "object".
To make matters worse consider the following snippet:

var s = "asd"
var f = function() { return this instanceof String }

An expression f.call(s) returns true,

As expected, see above. The primitive string value that is used as the
thisArg by Function.prototype.call() is converted to an object, a String
instance, when execution enters the function context [ES5, 10.4.3].
but (s instanceof String) returns false!

Yes, because `s' stores a primitive string value, not a reference to a
String instance.
The question is why call transforms this to an object?

It does not do that.
Is it made for unification, e.g. to make this iterable using 'for (var i
in this)' loop?

You are jumping to conclusions.
I see this might be a kind of boxing/unboxing in .NET, but I see no
reason why language designers made such a choice.

While the first result you observed could be a bug in your ECMAScript
implementation, it is more likely that you don't know what you are doing.


PointedEars
 
V

VK

The question is why call transforms this to an object?

Because you wanted it. call() sets the context of its first argument,
and it cannot be primitive value (string primitive in your case).
Javascript was originally made in the way to understand bad coding as
long as it's possible, with an armee of non-professional programmers
in mind. So instead of throwing illegal argument error, it wraps
string primitive into String object and works with it. Obviously it
doesn't affect the s string itself, it remains string primitive.
Same Javascript will do with other primitive, i.e.:

var n = 2;

function f() {
window.alert(this instanceof Number);
}


f.call(n); // alerts true

window.alert(typeof n); // number

It is also unclear why string literal in fact is not an instance of
String in ("asd" instanceof String) expression but it does a string
in  call/apply method invocations.

Again, in Javascript there are string primitives and string objects.
By default string literals create string primitives:
var s = "abc";
To make a string object one needs to use constructor:
var s = new String("abc");
but it has little practical sense: Javascript will "upcast" primitives
if needed and downcast when not needed anymore. Say
var len = s.length
it upcast and downcast s to get the length value - because string
primitive has no properties or methods, only String object does.
 
T

Thomas 'PointedEars' Lahn

Stefan said:
In ECMAScript 3, |this| is always an object. call() and apply() will
convert anything passed as the first argument (the "thisArg") to its
object form, except null and undefined:

| If thisArg is null or undefined, the called function is passed the
| global object as the this value. Otherwise, the called function is
| passed ToObject(thisArg) as the this value.
(ECMA-262, 3rd edition, 15.3.4.4)

ES5 specifies it differently, but to the same effect.
s is a string primitive (typof s == "string"), and |this| is a String
object (typeof this == "object").
Yes.

The conversion happened in call().

Depends.


PointedEars
 
T

Thomas 'PointedEars' Lahn

VK said:
Because you wanted it. call() sets the context of its first argument,
Nonsense.

and it cannot be primitive value (string primitive in your case).
Correct.

Javascript was originally made in the way to understand bad coding as
long as it's possible, with an armee of non-professional programmers
in mind.
Nonsense.

So instead of throwing illegal argument error, it wraps
string primitive into String object and works with it. Obviously it
doesn't affect the s string itself, it remains string primitive.
Correct.


Again, in Javascript there are string primitives and string objects.
By default string literals create string primitives:
var s = "abc";
To make a string object one needs to use constructor:
var s = new String("abc");
but it has little practical sense: Javascript will "upcast" primitives
if needed and downcast when not needed anymore. Say
var len = s.length
it upcast and downcast s to get the length value - because string
primitive has no properties or methods, only String object does.

True, except of "upcast" and "downcast" which are yet again products of your
vivid imagination, to put it politely.


PointedEars
 
L

Lasse Reichstein Nielsen

Thomas 'PointedEars' Lahn said:
ES5 specifies it differently, but to the same effect.

.... execept in strict mode functions, where the ThisBinding of function
need not be an object. (10.4.3, step 1).

/L
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,585
Members
45,080
Latest member
mikkipirss

Latest Threads

Top