2011-12-20 35 views
5

这个问题已经出来了another,其中涉及console.dir与字符串文字的行为。尤其请参阅my answer的评论。为什么String.prototype的方法可用于字符串文字?

众所周知,String JavaScript中的对象有许多方法。这些方法在String.prototype对象上定义。例如,String.prototype.toUpperCase。因此,我们可以做这样的事情:

var s = new String("hello"), 
    s2 = s.toUpperCase();  //toUpperCase is a method on String.prototype 

但是,我们也可以这样做:

var s = "hello",    //s is a string literal, not an instance of String 
    s2 = s.toUpperCase(); 

显然,JavaScript解释正在做某种形式的转换/施放的,当你调用String.prototype的方法在字符串文字上。但是,我在spec中找不到任何对此的提及。

它是有道理的,因为否则,在使用任何方法之前,您必须明确地将每个字符串文字转换为String对象,并且这会很烦人。

所以我的问题是,这个功能描述在哪里,我是否正确地假设文字值暂时被转换为String的实例?我是否过度思考这一点,并忽略了一些明显的东西

+1

顺便说一句'新的字符串(值)'表示法是100%无用的...不要使用它。 – 2011-12-20 21:00:20

+0

我知道是。问题是为什么。规范中描述了哪些内容? – 2011-12-20 21:00:56

+1

字符串文字是一个字符串对象:'typeof“hello”===“string”'返回true。这是否解决了这个问题? – bbg 2011-12-20 21:01:35

回答

7

它定义这里:

以下[[获取]]内部方法用于在getValue当V是与图元碱值的 属性参考。它被称为使用 基地作为它的这个值并且以属性P作为它的参数。采取以下步骤 :

  1. 设O为ToObject(base)。
  2. 设desc为调用属性名称为P的[[GetProperty]]的内部方法的结果。
  3. 如果desc未定义,则返回undefined。
  4. 如果IsDataDescriptor(desc)为true,则返回desc。[[Value]]。
  5. 否则,IsAccessorDescriptor(desc)必须为真,因此,让getter被描述为[[Get]]。
  6. 如果getter未定义,则返回undefined。
  7. 返回调用getter提供库的[[Call]]内部方法的结果作为该值并且不提供参数。

注意在上述方法之外,可能在步骤1中创建的对象不可访问 。实现可能会选择避免实际创建对象。使用此内部方法的这种实际属性访问唯一可见的 效果是当它调用访问器函数时。

来源:http://es5.github.com/#x8.7.1

的原始字符串值被强制转换到对象在步骤1


实施例1

var str = 'some string'; 
str = str.toUpperCase(); 

这里,表述str.toUpperCase是根据在11.2.1 Property Accessors定义的语义进行评估:

  1. 标识符str根据标识符解析(见10.2.2.1 GetIdentifierReference)来评价。结果是一个引用,其基值是当前词汇环境的环境记录,其引用名称为"str"。该参考文献是baseReference
  2. baseValue通过执行GetValue(baseReference)来确定。由于baseReference不是属性引用(其基本值不是对象或原始值,而是环境记录),因此将调用GetBindingValue()方法以检索引用的值。该方法返回局部变量str的值,即基元字符串值'some string'。该值是baseValue
  3. propertyNameValue求值为原始字符串值'toUpperCase'。 (为简单起见,我略微缩短了此过程。)
  4. 创建一个新的引用,其基值为baseValue,其引用的名称为propertyNameValue

因此,有参与这一进程的两个引用:

  • str(基值:环境记录,引用名称:'str'
  • str.toUpperCase(基值:'some string',引用的名字: 'toUpperCase'

最后,调用运算符()在后面的引用上执行。该引用的值根据此答案顶部定义的语义确定。

实施例2

var str = 'some string'.toUpperCase(); 

这里,表述'some string'.toUpperCase根据相同的 “属性访问” 的语义被评估如实施例1:

  1. 的字符串文字'some string'明显计算结果为原始字符串值'some string'。这是baseReference。 (不要让名称让你感到困惑 - 这是一个字符串值,不是参考。)
  2. baseValue通过执行GetValue(baseReference)来确定。由于baseReference不是参考,所以该方法简单地返回参数值,即baseValue = baseReference

正如你所看到的,就像例1中,baseValue是原始字符串值'some string'。步骤3和4是等价于实例中的步骤3和4 1.

所以,两者的标识参考str和字符串文字'some string'评价为相同的值 - 的原始字符串值'some string' - 并使用该值作为baseValue为新的参考,然后用()调用。由于这个引用有一个基本的基本值,所以在我的答案的开头定义的语义适用。

+0

啊哈!非常感谢你:) – 2011-12-20 21:12:50

+0

我也读过,但如何与参考相关的字符串文字?什么是引用,或者更确切地说,什么是已解析的名称绑定? – 2011-12-20 21:15:05

+0

'+ 1' - 我在找那个! – 2011-12-20 21:16:10

1

the reference文字转换为对象:

字符串(双或单引号表示)和字符串 返回从字符串中调用非构造函数上下文(即没有使用新关键字的 )是原始字符串。 JavaScript自动地将 转换为基本字符串和字符串对象,因此可以使用 字符串对象方法来处理基本字符串。

+0

这就如我所设想的那样,但我仍然无法在ECMAScript规范中找到它。你知道这个行为在那里描述吗? – 2011-12-20 21:06:05

相关问题