简体   繁体   English

为什么javascript在传递给function.apply()或function.call()时会改变原始类型?

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

It seems that when using a primitive type (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 (eg a string turns into a String). 看来,当使用一个原语类型(字符串,号码)作为this函数调用的对象(作为第一个参数要么function.call()或函数应用于())时,原始类型被提升到它的对象当量(例如,一个字符串变成一个字符串)。

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. 也就是说,“this”成为一个对象(它是一个String对象,我已经检查过),而第二个调用参数成为函数“f”的第一个参数,并且仍然是一个原始字符串。

The objects are both "123", but subtle things don't work (for example, they are equal in terms of "==" but not in terms of "==="). 对象都是 “123”,但微妙的东西不起作用(例如,它们在“==”方面相同,但在“===”方面则不相同)。

I've noticed this behaviour in both chrome and firefox, so I'm assuming there's a specific reason for it. 我在chrome和firefox中都注意到了这种行为,所以我假设它有一个特定的原因。 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 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. Function.prototype.call - 被调用的函数作为此值传递给ToObject (thisArg)。

ToObject "converts its argument to a value of type Object according to the following": ToObject “根据以下内容将其参数转换为Object类型的值”:

String - Create a new String object whose [[value]] property is set to the value of the string. String - 创建一个新的String对象,其[[value]]属性设置为字符串的值。

First parameter in Javascript function call & Apply methods determine in which context the requested function has to be run. Javascript函数调用和Apply方法中的第一个参数确定必须在哪个上下文中运行所请求的函数。 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. obj.ff.call(this,'sam')抛出一个错误。 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方法要在fun(或这里的窗口)的上下文中执行,而不是在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. obj.ff.call(obj1,'sam')告诉调用在totest1()的上下文中执行ff,并且它有效,因为它得到了方法测试。

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. 短期和简单的:第一个参数变成如果物体是一个原始类型的,因为,正如你指出的那样,可能被提及this在被调用的函数。 As this must refer to an object, the runtime environment makes sure there actually is an object to refer to. 由于this必须指向一个对象,运行时环境可以确保有实际上一个对象引用。 Think about how you would implement it, and you will probably come to the same conclusion. 想想你将如何实现它,你可能会得出同样的结论。 Good question. 好问题。

PS: I appreciate Ramesh's answer, which is technically illustrative, but wanted to add an answer for the impatient reader. PS:我很欣赏Ramesh的答案,这在技术上是说明性的,但是想为不耐烦的读者添加一个答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM