有人可以解释为什么执行以下操作会导致获取toUpperCase函数吗?
( “串”)[ “toUpperCase”]
function toUpperCase()
答案 0 :(得分:1)
编辑:我发现这个问题很有趣,所以我会尝试提供详细的答案。
另外,请允许我将您的示例更改为:
("hello")["toUpperCase"]
使用" string "可能误导编程新手(例如"字符串"是一个字符串)。
因为("hello")
临时转换为String对象,其属性["toUpperCase"]
具有对Function实例的引用。当你这样做时:
console.log( ("hello")["toUpperCase"] );
您正在访问该属性的值,即对toUpperCase
函数的引用。
让我们将("hello")["toUpperCase"]
分成几部分:
("hello")
评估为字符串文字(原语数据类型)。["toUpperCase"]
访问方法(包含函数定义的属性)。("hello")
我们继续打破:
毫无疑问, "hello"
是一个字符串文字:
console.log( typeof "hello" ); // Logs "string"
当我们将它包装在括号中(grouping operator)时,它将成为带括号的表达式。正如您可以阅读ECMAScript specification:
ParenthesizedExpression :(表达式)
返回评估Expression的结果。这可能是参考类型。
这意味着带括号的表达式计算括号内表达式的值。结果:
console.log( "hello" === ("hello") ); // Logs "true"
console.log( typeof ("hello") ); // Logs "string"
因此,我们可以得出结论("hello")
评估为字符串文字。
["toUpperCase"]
正如您在MDN中所读到的那样,括号符号在访问对象的属性时与点符号一样有效:
属性访问器通过使用提供对对象属性的访问 点符号或括号表示法。
<强>语法强>
object.property object["property"]
现在,如果toUpperCase
是一种方法,也许你想知道为什么我会谈论属性。如果您继续阅读上面的相同链接:
可以将对象视为关联数组(a.k.a. map, 字典,哈希,查找表)。这个数组中的键是名称 对象的属性。谈到一个对象时,这是典型的 用于区分属性和方法的属性。 但是,属性/方法的区别仅仅是a 惯例。方法只是一个可以被调用的属性 例如,如果它将一个Function实例的引用作为其值。
实际上,ECMAScript规范defines method为&#34;函数是属性的值&#34;。
因此,我们可以得出结论["toUpperCase"]
是一个属性访问器(提供对对象属性的访问)。
("hello")["toUpperCase"]
我们已经看到("hello")["toUpperCase"]
相当于"hello".toUpperCase
,实际上是:
console.log( ("hello")["toUpperCase"] === "hello".toUpperCase ); // Logs "true"
但是,为什么这有效? "hello"
不是对象!它是字符串文字(原语)!
这是完全正确的:
console.log( typeof "hello" ); // Logs "string"
console.log( typeof new String("hello") ); // Logs "object"
但JavaScript会将该文字强制转换为对象,因此您可以使用toUpperCase
方法。您可以在MDN中阅读 String全局对象的定义:
字符串文字(用双引号或单引号表示)和字符串 在非构造函数上下文中从String调用返回(即,没有 使用new关键字)是原始字符串。 JavaScript自动 将基元转换为String对象,以便可以使用它 原始字符串的字符串对象方法。在某种情况下 方法将在原始字符串或属性查找上调用 发生时,JavaScript会自动换行字符串原语和 调用方法或执行属性查找。
之后将丢弃该对象(MDN - Grammar and types):
您可以在字符串上调用String对象的任何方法 文字值 - JavaScript自动将字符串文字转换为 一个临时的String对象,调用该方法,然后丢弃 临时String对象。
因此我们可以得出结论:("hello")["toUpperCase"]
正在从(临时)String对象&#34; hello&#34;中访问toUpperCase
方法/属性。
因为这是对象属性中的内容:它是属性的值。据说JavaScript中的函数是&#34;一等公民&#34;,这意味着你可以像任何其他数据一样传递它们。你可以这样做:
var foo = new String( "I am foo" );
foo.upperCase = ("hello")["toUpperCase"];
console.log( foo.upperCase() ); // Logs "I AM FOO"
如果你想要的是调用方法,你需要使用函数调用操作符 ()
。
console.log( ("hello")["toUpperCase"]() ); // Logs "HELLO"