【问题标题】:Why does javascript change primitive types when passed into function.apply() or function.call()?为什么 javascript 在传递给 function.apply() 或 function.call() 时会更改原始类型?
【发布时间】:2010-02-19 08:13:19
【问题描述】:

似乎当使用原始类型(字符串、数字)作为函数调用的 this 主题(作为 function.call() 或函数 apply() 的第一个参数)时,原始类型被提升到它的等效对象(例如,一个字符串变成一个字符串)。

举例说明:

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

也就是说,“this”变成了一个对象(它是一个字符串对象,我已经检查过了),而调用的第二个参数变成了函数“f”的第一个参数,并且仍然是一个原始字符串。

对象都是都是“123”,但微妙的东西不起作用(例如,它们在“==”方面相等,但在“===”方面不相等) .

我在 chrome 和 firefox 中都注意到了这种行为,所以我假设这是有特定原因的。我已经搜索过,但没有找到任何解释。我会很感激任何解释,希望有某种文档链接解释有关此的规则及其发生的原因。

【问题讨论】:

    标签: javascript


    【解决方案1】:

    这似乎是正确的行为。

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

    Function.prototype.call - 被调用的函数作为 this 值传递 ToObject(thisArg)。

    ToObject“根据以下内容将其参数转换为Object类型的值”:

    String - 创建一个新的 String 对象,其 [[value]] 属性设置为字符串的值。

    【讨论】:

    • 真的很高兴找到 J-P。非常有趣的问题(和答案 ofc)。至少对我来说少了一个 JavaScript WTF =)
    • 不仅看起来正确,而且完全正确。优秀的来源。
    • 啊,非常感谢!我很想知道为什么 toObject() 被调用,但我不认为推理在任何地方的规范中。我记得在某处读到原始字符串上的方法是通过将它们临时转换为 String 对象并返回来解决的,所以这可能是类似的情况......
    【解决方案2】:

    Javascript 函数调用和应用方法中的第一个参数决定了请求的函数必须在哪个上下文中运行。 所以这将永远是一个对象

    为了说明这一点,请查看以下示例

    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') 抛出错误。 为什么

    因为我们指定了 obj.ff 方法在 fun 的上下文(或者这里是一个窗口)而不是 totest 的上下文中执行。

    obj.ff.call(obj1, 'sam') 告诉调用在 totest1() 的上下文中执行 ff,并且由于它得到了方法 test,所以它可以工作。

    所以这必须是对象。

    调用方法中剩余的参数是要执行的方法的真实参数。所以他们会根据给定的值推断类型。

    希望你现在能理解

    【讨论】:

    • 本例中出现类型错误的原因是因为ff函数调用this.test。在fun 中,this 的值实际上设置为全局window 对象(这是常规函数中this 的默认值)。所以ff被调用时this等于window,而window对象根本就没有调用test的方法。
    • @gfxmonk,确实是的..这意味着调用方法中的param1必须是一个对象,因此它可以在param1对象的上下文中调用ff方法。这就是分配给 param1 的任何类型值(无论其是否为原始类型)都将转换为对象的原因。我已经用另一个功能更新了答案。请检查
    【解决方案3】:

    简短而简单:如果第一个参数是原始类型,则将其转换为对象,因为正如您所指出的,它可能在被调用函数中由this 引用。由于this 必须引用一个对象,因此运行时环境会确保确实有是 一个要引用的对象。想想你将如何实现它,你可能会得出同样的结论。好问题。

    P.S.:我很欣赏 Ramesh 的回答,它在技术上是说明性的,但想为不耐烦的读者添加一个答案。

    【讨论】:

      猜你喜欢
      • 2016-11-20
      • 2010-10-14
      • 2014-10-03
      • 1970-01-01
      • 2020-10-04
      • 1970-01-01
      • 1970-01-01
      • 2018-06-18
      • 1970-01-01
      相关资源
      最近更新 更多