JS中的字面量变量为什么会有方法?

var num = 4;
num.toString();// 4
var nnum = new Number(4)
nnum.toString(); // 4

clipboard.png

clipboard.png

从浏览器里可以看出,这个num变量已经和nnum已经别无二致了。

clipboard.png
但是这里又不同,这是怎么做到的?

阅读 4.3k
6 个回答

我看了你对其他答案的评论,你希望看到比较权威的 ECMAScript 规范:

num.toString() 是一个属性访问运算符 Property Accessors,具体规范在 https://www.ecma-internationa... 具体的分类是:

MemberExpression . IdentifierName

而 MemberExpression 的规范在 https://www.ecma-internationa... 里面列了很多,但是在这个例子中,属于

PrimaryExpression

我们继续跟踪 PrimaryExpression,规范定义在 https://www.ecma-internationa...

num 属于 IdentifierReference

如果写 10.36.toString() 则属于 Literal。

(10).toString() 中,(10) 属于括号表达式。


所以在 num.toString() 中,num 属于 MemberExpression,toString 属于 IdentifierName,. 就是 Property Accessors

  1. Let baseReference be the result of evaluating MemberExpression.
  2. Let baseValue be ? GetValue(baseReference).
  3. Let bv be ? RequireObjectCoercible(baseValue).
  4. Let propertyNameString be StringValue of IdentifierName.
  5. If the code matched by this MemberExpression is strict mode code, let strict be true, else let strict be false.
  6. Return a value of type Reference whose base value component is bv, whose referenced name component is propertyNameString, and whose strict reference flag is strict.

看到上面的 RequireObjectCoercible 了吗?这就是你要的答案。

自动装箱了解一下

var num = 4; // num 为基本类型number
num.toString();// 4   Number(num).toString()  包装器
var nnum = new Number(4) // 显示定义一个Number对象
nnum.toString(); // 4

typeof num; // number
typeof nnum; // object

请参考JavaScript高级程序设计 第5章 5.6节基本包装类型

为了便于操作基本类型值,ECMAScript 还提供了 3 个特殊的引用类型: Boolean 、 Number 和
String 。这些类型与本章介绍的其他引用类型相似,但同时也具有与各自的基本类型相应的特殊行为。
实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们
能够调用一些方法来操作这些数据。来看下面的例子。
var s1 = "some text";
var s2 = s1.substring(2);
这个例子中的变量 s1 包含一个字符串,字符串当然是基本类型值。而下一行调用了 s1 的
substring() 方法,并将返回的结果保存在了 s2 中。我们知道,基本类型值不是对象,因而从逻辑上
讲它们不应该有方法(尽管如我们所愿,它们确实有方法)。其实,为了让我们实现这种直观的操作,
后台已经自动完成了一系列的处理。当第二行代码访问 s1 时,访问过程处于一种读取模式,也就是要
从内存中读取这个字符串的值。而在读取模式中访问字符串时,后台都会自动完成下列处理。
(1) 创建 String 类型的一个实例;
(2) 在实例上调用指定的方法;
(3) 销毁这个实例。
可以将以上三个步骤想象成是执行了下列 ECMAScript 代码。
var s1 = new String("some text");
var s2 = s1.substring(2);
s1 = null;
经过此番处理,基本的字符串值就变得跟对象一样了。而且,上面这三个步骤也分别适用于 Boolean
和 Number 类型对应的布尔值和数字值。
var num = 4;
num.toString();// 4
var nnum = new Number(4)
nnum.toString(); // 4

num是一个原始类型的值,可以自动当作对象调用,即调用各种对象的方法和参数。这时,JavaScript 引擎会自动将原始类型的值转为包装对象实例,在使用后立刻销毁实例。
使用new Number()时,会将原始数据类型转为对象,所以nnum instanceof Number输出为true。
具体可以查看下包装对象。

基本类型在进行点操作时会被转化为包装类型。 这也就是为什么说JS中万物皆对象的原因

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题