分配给{} .toString意味着什么?

时间:2015-09-16 14:54:52

标签: javascript function tostring

我正在学习JavaScript而且我遇到了这个片段,它演示了类型检测:

var toClass = {}.toString // Copy a reference to toString for objects into toClass variable

alert( toClass.call( [1,2] ) ) // [object Array]
alert( toClass.call( new Date ) ) // [object Date]

我不明白第一行的空花括号是什么,所以我将它们删除如下:

var toClass = toString

代码仍然有效。 但是在下面的代码中,

function getAge () {
    alert(this.age);
}

var p1 = {
    age:1
};

var tellAge=getAge;
tellAge.call(p1); //1

如果我将var tellAge=getAge更改为var tellAge={}.getAge,则会收到错误:无法读取未定义的属性“call”。 为什么是这样?是因为toString是内置函数吗?

4 个答案:

答案 0 :(得分:7)

  

是因为toString是一个内置函数

不完全是因为javascript中的Objectwindow都有toString方法。

{}中的{}.toString代表javascript中的新对象。对象具有toString方法,这就是您创建对。

的引用

如果省略{}它等同于window.toString,幸运的是window对象本身有toString方法。所以一切都继续有效。

当您执行{}.getAge时,您告诉口译员从对象中获取getAge方法,该方法不存在,将tellAge设置为undefined,这会导致错误cannot read property "call" of undefined

答案 1 :(得分:1)

  • {}会返回Object (1)类型的新对象。
  • toString()返回表示对象(2)的字符串。
  • 对于Object类型的对象,toString()应返回值[object Object]
  • call()执行具有给定this值的方法和单独提供的参数(3)
  • 任何未明确指定为对象方法的函数都会隐式分配给Window对象。在此类函数中使用this始终引用Window对象。

现在,让我们回到你的代码,好吗?!

var toClass = {}.toString

首先创建一个Object类型的通用对象。然后它返回方法toString(方法本身,而不是返回值。

这意味着toClass现在是一个函数。它使用对象{}作为this值。因此,如果您只是运行toClass(),则应始终获得值[object Object]

现在,这是棘手的一点!

执行此命令:

toClass.call( [1,2] )

这里发生了什么?嗯,这类似于调用toClass(),但您的this值不再是{}。相反,它会被[1,2] (4)取代。这就是为什么你得到[object Array]的结果!

现在接受此命令:

toClass.call( new Date )

这里发生了什么?嗯,同样的事情,真的。这与调用toClass()toClass.call( [1,2] )类似,只是您的this值被Date (5)类型的对象替换。这就是为什么你得到[object Date]的结果!

现在,请使用此功能:

function getAge () {
    alert(this.age);
}

这里发生了什么?好吧,此函数只会警告方法中age值的属性this。默认情况下,此属性未知,因为this值为WindowWindow对象没有age属性。

现在,请执行以下命令:

var p1 = {
    age:1
};

在这里,您创建一个只有一个属性的对象。该属性为age,其值为1.

现在,请执行以下命令:

var tellAge=getAge;

在此,您将函数getAge指定给变量tellAge。默认情况下,两个函数都使用相同的this值,即Window对象。

tellAge.call(p1);

这里发生了什么?好吧,它与调用tellAge()getAge()几乎相同,只是您的this值不再是Window。相反,它被p1取代。结果是1,因为对象p1有一个属性age,该属性的值为1!

现在,让我们检查以下命令:

var tellAge={}.getAge

为什么会产生错误?你在这里要做的是创建一个Object类型的通用对象。虽然默认情况下它具有toSting方法(在原型(6)中定义),但它没有getAge方法。这就是你收到错误的原因。

现在请使用以下代码:

var p2 = {
    age : 18
};

var p3 = {
    age : 25
};

var FObject = {
    getage : function() {
        return this.age;
    }
};

var tellAge = FObject.getage;
alert( tellAge.call(p2) ); //18
alert( tellAge.call(p3) ); //25

这是做什么的?好吧:

  • 首先,您创建一个名为p2的对象,该对象具有值为18的age属性。
  • 然后,您创建一个名为p3的对象,该对象具有值为25的age属性。
  • 然后,您创建另一个名为FObject的对象对象,该对象具有getage方法。
  • 然后,您将方法FObject.getage分配给变量tellAge
  • 然后,您拨打tellAge.call(p2)。这与调用tellAge()类似,只是您的this值被对象p2替换。这就是为什么你得到18的结果!
  • 最后,您致电tellAge.call(p3)。这与调用tellAge()tellAge.call(p2)类似,只是您的this值被对象p3替换。这就是为什么你得到25的结果!

我相信最后一个例子很好地概述了你正在研究的行为。

参考文献:

  1. Object
  2. Object.prototype.toString()
  3. Function.prototype.call()
  4. Array
  5. Date
  6. Object.prototype

答案 2 :(得分:1)

哦,我的...在很短的时间内要回答很多事情......但是你还有很长的路要走JavaScript,但是你会爱上它...... < / p>

1)对象表示法。你应该google for JSON。

对象表示法意味着,您可以使用与JavaScript相关的特定格式定义数据。

  对象表示法中的

{}表示一个对象......更具体地说,这已经是一个对象的实例。

你也可以用普通的javascript写这个,它看起来像这样:

new Object()

2)职能是一等公民。

嗯,功能确实是JS生态系统中非常有价值的资产。这意味着你可以基本上做任何你想象的事情。这包括复制对属于&#34;属于&#34;的函数的引用。另一个对象。

  

{}。toString是一个函数。您通常会通过执行{} .toString()

来调用它      

相反,只需在变量中复制对函数的引用即可。在这种情况下,你&#34;存储&#34;变量&#34; toClass&#34;

中的函数

3)原型链。你应该谷歌,好吧,原型链哈哈。

原型链,简单来说就是&#34;喜欢&#34;类继承。所以这意味着如果一个A类有一个方法&#34; blah&#34;而B班是一个孩子&#34; A级,这个,好吧,也有方法&#34; blah&#34;。

  

在JS世界中,原型链的顶部是&#34; Object&#34;。许多函数已经在Object的原型中定义。包括&#34; toString&#34;

4)广义相对论问题...... a.k.a. this,call,and apply。

由于函数是一等公民,它们基本上可以存在,甚至不属于特定的对象实例。

  

这意味着,您可以选择要在哪个上下文中调用该函数。

默认情况下,当您调用似乎&#34;附加&#34;对象,该对象成为该函数调用的 this 上下文:

{}.toString()    // This executes toString in the context of {}

但正如我所说,你可以选择功能实际执行的位置。为此,方法&#34;呼叫&#34;并且&#34;申请&#34;存在。

我们之前的例子可以翻译成:

Object.prototype.toString.call({})  // This executes toString in the context of {}

5)环境中的全局对象。

这不是一个简单的主题,因为现在JavaScript不仅在浏览器上运行,而且在服务器上运行...... NodeJS就是一个很好的例子。

假设您在浏览器中运行此操作...有一个名为窗口的全局对象

您基本上可以调用全局对象中的任何函数。

  

所以toString相当于 window .toString,window是Object的后代,它也会从Object.prototype中获取方法。

现在回答

  

getAge 未在Object.prototype中定义,因此您无法调用不存在的函数。

答案 3 :(得分:0)

刚刚做了这个例子,向你说清楚。 Jsfiddle

var toClass = {}.toString; // type detection

function person(age){
    this.age = age;
    this.getAgePlusOne = function(){
        return this.age + 1;
    };
}

var you = new person(20); // create a new person object and set age propery to 20
console.log(you);
var yourAge = you.getAgePlusOne(); // call created person object's function getAgePlusOne() to retrieve value
console.log(yourAge);

console.log(toClass.call(you)); // object
console.log(toClass.call(you.getAgePlusOne)); //function