开发者

Why does javascript change primitive types when passed into function.apply() or function.call()?

It seems that when using a primitive t开发者_JS百科ype (string, number) as the this subject of a function call (as the first argument to either function.call() or function apply()), the primitive type is promoted to its object equivalent (e.g a string turns into a String).

To illustrate:

var f = function(x) { return [typeof(this), typeof(x)]; }  
var obj = '123'  
f.call(obj, obj)  
>>> ["object", "string"]  

That is, "this" becomes an object (it's a String object, I've checked) while the second argument to call becomes the first argument to the function "f", and remains a primitive string.

The objects are both "123", but subtle things don't work (for example, they are equal in terms of "==" but not in terms of "===").

I've noticed this behaviour in both chrome and firefox, so I'm assuming there's a specific reason for it. I've searched, but not found any explanation. I'd appreciate any explanation, hopefully with some sort of link to documentation explaining the rules around this and why it occurs.


This seems to be the correct behaviour.

http://bclary.com/2004/11/07/#a-15.3.4.4

Function.prototype.call - The called function is passed ToObject(thisArg) as the this value.

ToObject "converts its argument to a value of type Object according to the following":

String - Create a new String object whose [[value]] property is set to the value of the string.


First parameter in Javascript function call & Apply methods determine in which context the requested function has to be run. So this will always be a object

To illustrate this, checkout the below example

function totest() 
{
    this.ff  = function(x) {
        this.test(x);
    };

    this.test = function(x) {
        alert(x);
    }

}

function totest1() 
{   
 this.test = function(x) {
    alert(x);
}

}

function fun() 
{
     var obj = new totest();
     var obj1 = new totest1();
     obj.ff('hi');  //Runs fine without any problem
     obj.ff.call(obj, 'sam') ;  //Runs fine without any problem
     obj.ff.call(this, 'sam');  //throws an error
     obj.ff.call(obj1, 'sam');  //will be executed in the context of totest1

}

obj.ff.call(this, 'sam') throws an error. WHY

Because we specify the obj.ff method to be executed in the context of fun (or a window here) not in the context of totest.

obj.ff.call(obj1, 'sam') tells the call to execute the ff with in the context of totest1(), and it works since it got the method test.

so this has to be object.

And the remainning params in call method are real ones for the method to be executed. So they wil infer the type from the given value.

Hope you can understand now


Short and simple: The first parameter is turned into an object in case it is of a primitive type because, as you pointed out, it might be referred to by this in the called function. As this must refer to an object, the runtime environment makes sure there actually is an object to refer to. Think about how you would implement it, and you will probably come to the same conclusion. Good question.

P.S.: I appreciate Ramesh's answer, which is technically illustrative, but wanted to add an answer for the impatient reader.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜