为什么String.prototype的方法可用于字符串文字?

Jam*_*ice 5 javascript

这个问题来自另一个问题,它涉及console.dir字符串文字的行为.特别是,请参阅我的回答评论.

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

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

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

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

很明显,当您String.prototype在字符串文字上调用方法时,JavaScript解释器正在进行某种形式的转换/转换.但是,我在规范中找不到任何对此的引用.

这是有道理的,因为否则你必须明确地将每个字符串文字强制转换为一个String对象,然后才能使用任何方法,这将非常烦人.

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

Šim*_*das 8

它在这里定义:

当V是具有基本基值的属性引用时,GetValue使用以下[[Get]]内部方法.使用base作为其值并使用属性P作为其参数调用它.采取以下步骤:

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

注意在上述方法之外无法访问可能在步骤1中创建的对象.实现可能会选择避免实际创建对象.使用此内部方法的此类实际属性访问可以具有可见效果的唯一情况是它调用访问器函数时.

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

在步骤1中将原始字符串值强制转换为对象.


例1

var str = 'some string';
str = str.toUpperCase();
Run Code Online (Sandbox Code Playgroud)

这里,表达式str.toUpperCase根据11.2.1属性访问器中定义的语义进行评估:

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

因此,此过程涉及两个引用:

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

最后,调用操作符()在后一个引用上执行.该引用的值是根据本答案顶部定义的语义确定的.

例2

var str = 'some string'.toUpperCase();
Run Code Online (Sandbox Code Playgroud)

这里,表达式'some string'.toUpperCase根据与示例1中相同的"Property Accessor"语义进行评估:

  1. 字符串文字'some string'明显地计算为原始字符串值'some string'.这是baseReference.(不要让名称混淆你 - 这是一个字符串值,而不是引用.)
  2. baseValue通过执行确定GetValue(baseReference).由于baseReference不是引用,因此该方法只返回参数值,即baseValue = baseReference.

如您所见,就像在示例1中一样,baseValue是原始的String值'some string'.步骤3和4等同于示例1中的步骤3和4.

因此,标识符引用str和字符串文字都'some string'评估为相同的值 - 原始字符串值'some string'- 并且该值用作新引用的baseValue,然后调用该引用().由于此引用具有原始基值,因此在我的答案开头定义的语义适用.