调用字符串原型的方法

时间:2015-08-30 06:23:21

标签: javascript methods

有人可以解释为什么执行以下操作会导致获取toUpperCase函数吗?

( “串”)[ “toUpperCase”]

  
    

function toUpperCase()

  

1 个答案:

答案 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"