【问题标题】:What is the .call() function doing in this Javascript statement?这个 Javascript 语句中的 .call() 函数在做什么?
【发布时间】:2010-07-14 20:47:48
【问题描述】:

我正在积极学习javascript,我遇到了以下声明:

Object.prototype.toString.call([]); 

而且我不知道它的含义或作用。

我对@9​​87654322@ 有一个模糊的理解,因为它允许您在不同对象的上下文中调用方法(我认为),但我很难理解.call() 函数的作用是什么在上述声明中播放。所以我想知道是否有人可以解释.call() 在这里做什么?

谢谢!!

【问题讨论】:

    标签: javascript


    【解决方案1】:

    call 方法将调用函数的 this 值设置为作为第一个参数传递的对象,在您的示例中,您正在对 Array 对象执行 Object.prototype.toString 方法。

    数组对象,有自己的 toString 方法 (Array.prototype.toString),它会隐藏来自 Object.prototype 的那个,如果您调用 [].toString();,则将调用 Array.prototype 上的方法。

    例如:

    function test() {
      alert(this);
    }
    test.call("Hello"); // alerts "Hello"
    

    另一个例子:

    var alice = {
      firstName: 'Alice',
      lastName: 'Foo',
      getName: function () {
        return this.firstName + ' ' + this.lastName;
      }
    };
    
    var bob = {
      firstName: 'Bob',
      lastName: 'Bar',
    };
    
    alice.getName.call(bob); // "Bob Bar"
    

    在上面的例子中,我们在 Bob 的对象上使用了 Alice 的 getName 方法,this 的值指向 bob,所以该方法的工作原理就像它是在第二个对象上定义的一样。

    现在我们来谈谈Object.prototype.toString 方法。 JavaScript 中的所有原生对象都包含一个名为 [[Class]]internal 属性,该属性包含一个字符串值,该值表示对象的分类规范定义,的可能值本机 对象是:

    • "Object"
    • "Array"
    • "Function"
    • "Date"
    • "RegExp"
    • "String"
    • "Number"
    • "Boolean"
    • "Error" 用于错误对象,例如 ReferenceErrorTypeErrorSyntaxErrorError 等的实例
    • "Math" 代表全局 Math 对象
    • "JSON" 用于在 ECMAScript 第 5 版中定义的全局 JSON 对象。规格。
    • "Arguments" 用于 arguments 对象(也在 ES5 规范中引入。)
    • "null"(几天前在ES5 errata中介绍过)
    • "undefined"

    正如我之前所说的,该属性是 internal,没有办法改变它,规范没有提供任何操作符或内置函数来做到这一点,而 只有你可以通过Object.prototype.toString方法访问它的值。

    这个方法返回一个由以下组成的字符串:

    "[object " + this.[[Class]] + "]"
    

    仅用于说明目的,因为无法直接访问[[Class]]

    例如:

    Object.prototype.toString.call([]);       // "[object Array]"
    Object.prototype.toString.call(/foo/);    // "[object RegExp]"
    Object.prototype.toString.call({});       // "[object Object]"
    Object.prototype.toString.call(new Date); // "[object Date]"
    // etc...
    

    这对于以安全的方式检测对象的种类非常有用,对于检测数组对象,这是使用最广泛的技术:

    function isArray(obj) {
      return Object.prototype.toString.call(obj) == '[object Array]';
    }
    

    使用instanceof 运算符可能很诱人,但如果您在跨帧 环境中工作,这种方式会导致问题,因为在一帧上创建的数组对象不会instanceof Array 另一个的构造函数。

    上述方法将毫无问题地工作,因为该对象将完整地包含其[[Class]] 内部属性的值。

    另见:

    【讨论】:

    • +1,但这是一个奇怪的例子 isArray()... 涉及 typeof 或 instanceof 的方法似乎更简单。
    • @Jason, typeof 不太有用,对于数组对象,它只会返回“object”,另一方面,instanceof 有效,但在 cross-frame 环境(请参阅我的更新答案)。
    【解决方案2】:

    因为toString 大多不是用参数调用的,不是toString('foo'),而是bar.toString()。这就是call 派上用场的地方。

    不同的toStrings

    我说“大部分”是因为toStrings 不同:

    1. Object.prototype.toString 返回表示对象的字符串
    2. Array.prototype.toString 返回表示指定数组及其元素的字符串
    3. Number.prototype.toString 返回表示指定 Number 对象的字符串
    4. String.prototype.toString 返回代表指定 String 对象的字符串
    5. Function.prototype.toString返回一个字符串,代表函数的源代码

    单独使用实例

    (new Object()).toString();                // "[object Object]"
    ["foo", "bar"].toString();                // "foo,bar"
    (6).toString(2);                          // "110"
    ("meow").toString();                      // "meow"
    (function(){return 'x';}).toString()      // "function (){return 'x';}"
    

    虽然所有对象原型都继承自Object,但后者不会从ObjecttoString 继承toString,这意味着它们都是不同的东西,有不同的用途。要告诉对象的类型,Object.prototype.toString 是有用的,因为它返回一个类型:

    每个对象都有一个 toString() 方法,当对象被表示为文本值或以期望字符串的方式引用对象时,该方法会自动调用。默认情况下,toString() 方法被从 Object 派生的每个对象继承。如果自定义对象中没有重写此方法,则 toString() 返回“[object type]”,其中 type 是对象类型。

    呼叫

    注意,其中唯一带参数的是Number.prototype.toString,用于指定结果编号的基数。因此,要对数组、数字等有自己的toString方法的对象调用Object.prototype.toString,需要call指定this

    Object.prototype.toString.call(Math);         // [object Math]
    Object.prototype.toString.call(new Date);     // [object Date]
    Object.prototype.toString.call(new String);   // [object String]
    Object.prototype.toString.call(Math);         // [object Math]
    
    // Since JavaScript 1.8.5
    Object.prototype.toString.call(undefined);    // [object Undefined]
    Object.prototype.toString.call(null);         // [object Null]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多