JavaScript深入之原生函数

JavaScript 为基本数据类型值提供了封装对象,称为原生函数,常见的原生函数包括

  • String()
  • Number()
  • Boolean()
  • Array()
  • Object()
  • Function()
  • RegExp()
  • Date()
  • Error()
  • Symbol()

它们可以被当作构造函数来使用, 但其构造出来的对象可能会和我们设想的有所 出入

1
2
3
4
let a = new String('abc');
typeof a; // 是"object",不是"String"
a instanceof String; // true
Object.prototype.toString.call(a); // "[object String]"

通过构造函数(如 new String(“abc”) )创建出来的是封装了基本类型值(如 “abc” )的封 装对象。

内部属性[[Class]]

所有 typeof 返回值为 “object” 的对象(如数组)都包含一个内部属性 [[Class]] (我们可 以把它看作一个内部的分类,而非传统的面向对象意义上的类)。这个属性无法直接访问, 一般通过 Object.prototype.toString(..) 来查看。例如:

1
2
3
4
5
6
7
8
9
Object.prototype.toString.call([1, 2, 3]); // "[object Array]"
Object.prototype.toString.call(/regex-literal/i); // "[object RegExp]"

Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undefined); // "[object Undefined]"

Object.prototype.toString.call('abc'); // "[object String]"
Object.prototype.toString.call(42); // "[object Number]"
Object.prototype.toString.call(true); // "[object Boolean]"

内部属性和创建该对象的内建原生构造函数相对应,虽然 Null() 和 Undefined() 这样的原生构造函数并不存在,但是内部属性值仍 然是 “Null” 和 “Undefined” 。
其他基本类型值(如字符串、数字和布尔)的情况有所不同,它们的值被各自的封装对象自动包装,所以它们的内部属性值分别为 “String” 、 “Number” 和 “Boolean” 。

封装

原生函数为基本数据类型值提供了该子类型所特有的方法和属性(如:String#trim() 和 Array#concat(..))。

对于简单标量基本类型值,比如 “abc” ,如果要访问它的 length 属性或 String.prototype 方法, JavaScript 引擎会自动对该值进行封装(即用相应类型的封装对象来包装它)来实现对这些属性和方法的访问。

1
2
3
4
5
6
7
8
9
var a = 'abc';

a.length; // 3
a.toUpperCase(); // "ABC"

var b = new Boolean(false);
if (!b) {
console.log('Oops'); // 执行不到这里
}

拆封

如果想要得到封装对象中的基本类型值,可以使用 valueOf() 函数:

1
2
3
4
5
6
7
var a = new String('abc');
var b = new Number(42);
var c = new Boolean(true);

a.valueOf(); // "abc"
b.valueOf(); // 42
c.valueOf(); // true

参考文档

你不知道的 JavaScript(中卷)