分配给 {}.toString 是什么意思?
What does assigning to {}.toString mean?
我正在学习 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
是内置函数吗?
Is it because toString is a built-in function
不完全是,因为javascript中的Object
和window
都有一个toString
方法。
{}.toString
中的{}
表示javascript中的新对象。对象有一个 toString
方法,这就是您要创建的引用。
如果省略 {}
它等同于 window.toString
幸运的是 window
对象本身有一个 toString
方法。所以一切都继续工作。
当您执行 {}.getAge
时,您是在告诉解释器从不存在的对象中获取 getAge
方法,将 tellAge
设置为 undefined
,这导致错误 cannot read property "call" of undefined
{}
returns 一个类型为 Object
(1). 的新对象
toString()
returns 表示对象的字符串 (2).
- 对于
Object
类型的对象,toString()
应该 return 值 [object Object]
。
call()
使用给定的 this
值和单独提供的参数执行方法 (3).
- 任何未显式分配给对象的方法的函数都隐式分配给
Window
对象。在这样的函数中使用 this
总是引用 Window
对象。
现在,让我们回到您的代码,好吗?!
var toClass = {}.toString
这首先创建了一个 Object
类型的通用对象。然后 return 方法 toString
(方法本身,而不是 return 值。
这意味着 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);
}
这里发生了什么?嗯,这个函数只是提醒你方法中 this
值的 属性 age
。默认情况下,这个 属性 是未知的,因为 this
值是 Window
而 Window
对象没有 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
的对象,它有一个 age
属性 的值为 18。
- 然后,您创建一个名为
p3
的对象,它的 age
属性 值为 25。
- 然后,您创建另一个名为
FObject
的对象对象,它有一个 getage
方法。
- 然后,您将方法
FObject.getage
分配给变量 tellAge
。
- 然后,您调用
tellAge.call(p2)
。这类似于调用 tellAge()
,只是您的 this
值被对象 p2
替换了。这就是为什么您会得到 18
结果!
- 最后,你打电话给
tellAge.call(p3)
。这类似于调用 tellAge()
或 tellAge.call(p2)
,只是您的 this
值被对象 p3
替换。这就是为什么你得到 25
结果!
我相信最后一个示例很好地概述了您正在研究的行为。
参考资料:
只是举这个例子让你明白。 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
哦,天哪……在这么短的时间内要回答的事情太多了……但是你还有很长的路要走JavaScript,但你会爱上它的……
1) 对象表示法。对于 JSON,你应该 google。
对象表示法意味着,您可以使用与 JavaScript 相关的特定格式定义数据。
{ } in object notation means, an object... more specifically speaking, this is already an instance of an object.
你也可以写成普通的 javascript,它看起来像这样:
new Object()
2) 函数首先是 class 公民。
嗯,函数确实是 JS 生态系统中非常有价值的资产。这意味着你基本上可以用它们做任何你想做的事。这包括将对 "belongs" 的函数的引用复制到另一个对象。
{}.toString is a function. You would normally invoke it by doing {}.toString( )
You are instead, just copying the reference to the function in a variable. In this case you "store" the function in the variable "toClass"
3) 原型链。你应该google,嗯,原型链哈哈
原型链,简单来说就是"like"class继承。所以这意味着如果 class A 有一个方法 "blah" 并且 class B 是 A 的 "child" class,那么,这也将有方法"blah".
In JS world, the top of the prototype chain is "Object". And many functions are already defined in the prototype of Object. Including "toString"
4) 广义相对论问题...a.k.a。这个,打电话申请。
由于函数首先是 class 公民,因此它们基本上可以存在,甚至不属于特定的对象实例。
That means, you can choose on which this context you want the function to be invoked on.
默认情况下,当您调用对对象来说似乎是 "attached" 的函数时,该对象将成为该函数调用的 this 上下文:
{}.toString() // This executes toString in the context of {}
但正如我所说,您可以只选择函数实际执行的位置。为此,方法 "call" 和 "apply" 存在。
我们前面的例子可以翻译成:
Object.prototype.toString.call({}) // This executes toString in the context of {}
5) 您环境中的全局对象。
这不是一个简单的话题,因为现在 JavaScript 不仅可以在浏览器上运行,还可以在服务器上运行...NodeJS 就是一个很好的例子。
假设您在浏览器中 运行...有一个名为 window
的全局对象
您基本上可以调用全局对象中的任何函数。
So toString is equivalent to window.toString and window is descendent of Object, it will also get the method from the Object.prototype.
现在你的答案
getAge is not defined in Object.prototype, so you cannot invoke a non existing function.
我正在学习 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
是内置函数吗?
Is it because toString is a built-in function
不完全是,因为javascript中的Object
和window
都有一个toString
方法。
{}.toString
中的{}
表示javascript中的新对象。对象有一个 toString
方法,这就是您要创建的引用。
如果省略 {}
它等同于 window.toString
幸运的是 window
对象本身有一个 toString
方法。所以一切都继续工作。
当您执行 {}.getAge
时,您是在告诉解释器从不存在的对象中获取 getAge
方法,将 tellAge
设置为 undefined
,这导致错误 cannot read property "call" of undefined
{}
returns 一个类型为Object
(1). 的新对象
toString()
returns 表示对象的字符串 (2).- 对于
Object
类型的对象,toString()
应该 return 值[object Object]
。 call()
使用给定的this
值和单独提供的参数执行方法 (3).- 任何未显式分配给对象的方法的函数都隐式分配给
Window
对象。在这样的函数中使用this
总是引用Window
对象。
现在,让我们回到您的代码,好吗?!
var toClass = {}.toString
这首先创建了一个 Object
类型的通用对象。然后 return 方法 toString
(方法本身,而不是 return 值。
这意味着 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);
}
这里发生了什么?嗯,这个函数只是提醒你方法中 this
值的 属性 age
。默认情况下,这个 属性 是未知的,因为 this
值是 Window
而 Window
对象没有 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
的对象,它有一个age
属性 的值为 18。 - 然后,您创建一个名为
p3
的对象,它的age
属性 值为 25。 - 然后,您创建另一个名为
FObject
的对象对象,它有一个getage
方法。 - 然后,您将方法
FObject.getage
分配给变量tellAge
。 - 然后,您调用
tellAge.call(p2)
。这类似于调用tellAge()
,只是您的this
值被对象p2
替换了。这就是为什么您会得到18
结果! - 最后,你打电话给
tellAge.call(p3)
。这类似于调用tellAge()
或tellAge.call(p2)
,只是您的this
值被对象p3
替换。这就是为什么你得到25
结果!
我相信最后一个示例很好地概述了您正在研究的行为。
参考资料:
只是举这个例子让你明白。 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
哦,天哪……在这么短的时间内要回答的事情太多了……但是你还有很长的路要走JavaScript,但你会爱上它的……
1) 对象表示法。对于 JSON,你应该 google。
对象表示法意味着,您可以使用与 JavaScript 相关的特定格式定义数据。
{ } in object notation means, an object... more specifically speaking, this is already an instance of an object.
你也可以写成普通的 javascript,它看起来像这样:
new Object()
2) 函数首先是 class 公民。
嗯,函数确实是 JS 生态系统中非常有价值的资产。这意味着你基本上可以用它们做任何你想做的事。这包括将对 "belongs" 的函数的引用复制到另一个对象。
{}.toString is a function. You would normally invoke it by doing {}.toString( )
You are instead, just copying the reference to the function in a variable. In this case you "store" the function in the variable "toClass"
3) 原型链。你应该google,嗯,原型链哈哈
原型链,简单来说就是"like"class继承。所以这意味着如果 class A 有一个方法 "blah" 并且 class B 是 A 的 "child" class,那么,这也将有方法"blah".
In JS world, the top of the prototype chain is "Object". And many functions are already defined in the prototype of Object. Including "toString"
4) 广义相对论问题...a.k.a。这个,打电话申请。
由于函数首先是 class 公民,因此它们基本上可以存在,甚至不属于特定的对象实例。
That means, you can choose on which this context you want the function to be invoked on.
默认情况下,当您调用对对象来说似乎是 "attached" 的函数时,该对象将成为该函数调用的 this 上下文:
{}.toString() // This executes toString in the context of {}
但正如我所说,您可以只选择函数实际执行的位置。为此,方法 "call" 和 "apply" 存在。
我们前面的例子可以翻译成:
Object.prototype.toString.call({}) // This executes toString in the context of {}
5) 您环境中的全局对象。
这不是一个简单的话题,因为现在 JavaScript 不仅可以在浏览器上运行,还可以在服务器上运行...NodeJS 就是一个很好的例子。
假设您在浏览器中 运行...有一个名为 window
的全局对象您基本上可以调用全局对象中的任何函数。
So toString is equivalent to window.toString and window is descendent of Object, it will also get the method from the Object.prototype.
现在你的答案
getAge is not defined in Object.prototype, so you cannot invoke a non existing function.