String Constructor
```js
var str = new String("1");
console.info("str:", str);
```
![46-string][url-local-string]
Number Constructor
```js
var num = new Number(1);
console.info("num:", num);
```
![46-number][url-local-number]
Boolean Constructor
```js
var bool = new Boolean(true);
console.info("bool:", bool);
```
![46-bool][url-local-bool]
Object Constructor
```js
var obj = new Object();
console.info("obj:", obj);
```
![46-obj][url-local-obj]
Array Constructor
```js
var arr = new Array();
console.info("arr:", arr);
```
![46-arr][url-local-arr]
Function Constructor
```js
var func = new Function('console.info("func")');
console.info("func:", func);
```
![46-func][url-local-func]
constructor()
看下直接执行构造函数会有什么结果。
var str = String();
var num = Number();
var bool = Boolean();
var obj = Object();
var arr = Array();
var func = Function();
目录
引子
看了 ECMAScript 规范文档上关于对象的概述,算是一种参考。
Object
尽管 ECMAScript 有类的定义的语法,但从根本上讲,ECMAScript 对象并不是基于类,不像 C++、Smalltalk 或者 Java。ECMAScript 中可以通过各种方式创建对象,包含通过文字符号或者通过构造器创建对象 ,然后执行代码将初始值赋给它们的属性,初始化所有或部分它们自己的属性。每个
constructor
都是一个函数,它拥有一个名为prototype
的属性,是用来实现基于原型继承和属性共享。创建对象通过在new
表达式使用构造器。例如new Date(2009,11)
创建了一个新的Date
对象。没有通过new
调用一个constructor
的结果,取决于constructor
自身。例如Date()
产生一个代表当前日期和时间的字符串,而不是一个对象。constructor
创建的每个对象都有一个隐式引用(称为对象的原型),指向其constructor
的prototype
属性值。此外,原型可能具有对其原型的非null
隐式引用,以此类推,这就叫做原型链。当引用对象中的属性时,该引用是原型链中包含该名称属性的第一个对象中该名称的属性。换句话说,首先检查使用的对象中是否有该属性,如果对象包含这个名称的属性,那就是该引用指向的属性。如果这个对象不包含这个名称的属性,就会沿着这个对象的原型继续检查下去,依次类推。在一个基于类的面向对象的语言,通常,状态由实例承载,方法由类承载,而继承仅由结构和行为承载。在 ECMAScript 中,状态和方法都由对象承载,而结构,行为和状态都是继承的。
所有不直接包含其原型包含的特定属性的对象共享该属性及其值。下图说明这点:
CF 是一个 constructor。通过 new 表达式已经创建了 5 个对象:cf1 cf2 cf3 cf4 cf5。每个对象包含属性 q1 和 q2 。虚线代表着隐式原型关系;例如,cf3 的原型是 CFp。CF 拥有两个自己的属性,分别是 P1 和 P2,它们对 CFp、cf1、cf2、cf3、cf4、cf5 都是不可见。在 CFp 中的属性 CFP1 由 cf1、cf2、cf3、cf4、cf5 共享,在 CFp 的隐式原型链中找到的任何未命名为 q1、q2 或 CFP1 的属性也是如此。请注意,CF 和 CFp 之间没有隐式原型链接。
与大多数基于类的面向对象语言不同,可以通过为对象赋值来动态的添加属性。也就是说,构造函数不需要为所有或者任何构造对象的属性命名或赋值。在上图例子中,可以通过在 CFp 属性中添加一个新值,为 cf1、cf2、cf3、cf4、cf5 添加一个共享的属性。
虽然 ECMAScript 对象不是基于类的,但基于构造函数、原型对象和方法的常见模式来模仿类的抽象通常也方便。ECMAScript 内置对象本身遵循这种模仿类的模式。从 ECMA2015 开始,ECMAScript 语言包含了类语法定义,允许开发者更加简明的定义对象,这种方式也是根据内置对象使用的模仿类抽象模式。
补充
上面主要是逻辑上的文字描述,下面对里面的一些文字描述在代码中具体去看看。
new constructor()
看下几种常见类型
constructor
是什么样子的。String Constructor
```js var str = new String("1"); console.info("str:", str); ``` ![46-string][url-local-string]Number Constructor
```js var num = new Number(1); console.info("num:", num); ``` ![46-number][url-local-number]Boolean Constructor
```js var bool = new Boolean(true); console.info("bool:", bool); ``` ![46-bool][url-local-bool]Object Constructor
```js var obj = new Object(); console.info("obj:", obj); ``` ![46-obj][url-local-obj]Array Constructor
```js var arr = new Array(); console.info("arr:", arr); ``` ![46-arr][url-local-arr]Function Constructor
```js var func = new Function('console.info("func")'); console.info("func:", func); ``` ![46-func][url-local-func]constructor()
看下直接执行构造函数会有什么结果。
对象的原型
上文说的对象的原型,在打印的结果中可以发现,就是
__proto__
属性,原型链的形成靠的就是这个。而prototype
是函数独有的属性,是保存它们所有实例方法的真正所在,例如常见的toString()
和valueOf()
等方法实际上都保存在prototype
名下。在模仿类的继承特性时prototype
属性起到了很重要的作用。参考资料