XXHolic / segment

some notes
MIT License
28 stars 4 forks source link

Object Overview #48

Open XXHolic opened 5 years ago

XXHolic commented 5 years ago

目录

引子

看了 ECMAScript 规范文档上关于对象的概述,算是一种参考。

Object

尽管 ECMAScript 有类的定义的语法,但从根本上讲,ECMAScript 对象并不是基于类,不像 C++、Smalltalk 或者 Java。ECMAScript 中可以通过各种方式创建对象,包含通过文字符号或者通过构造器创建对象 ,然后执行代码将初始值赋给它们的属性,初始化所有或部分它们自己的属性。每个 constructor 都是一个函数,它拥有一个名为 prototype 的属性,是用来实现基于原型继承和属性共享。创建对象通过在 new 表达式使用构造器。例如 new Date(2009,11) 创建了一个新的 Date 对象。没有通过 new 调用一个 constructor 的结果,取决于 constructor 自身。例如 Date() 产生一个代表当前日期和时间的字符串,而不是一个对象。

constructor 创建的每个对象都有一个隐式引用(称为对象的原型),指向其 constructorprototype 属性值。此外,原型可能具有对其原型的非 null 隐式引用,以此类推,这就叫做原型链。当引用对象中的属性时,该引用是原型链中包含该名称属性的第一个对象中该名称的属性。换句话说,首先检查使用的对象中是否有该属性,如果对象包含这个名称的属性,那就是该引用指向的属性。如果这个对象不包含这个名称的属性,就会沿着这个对象的原型继续检查下去,依次类推。

在一个基于类的面向对象的语言,通常,状态由实例承载,方法由类承载,而继承仅由结构和行为承载。在 ECMAScript 中,状态和方法都由对象承载,而结构,行为和状态都是继承的。

所有不直接包含其原型包含的特定属性的对象共享该属性及其值。下图说明这点:

40-figure

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 语言包含了类语法定义,允许开发者更加简明的定义对象,这种方式也是根据内置对象使用的模仿类抽象模式。

Back to top :arrow_up:

补充

上面主要是逻辑上的文字描述,下面对里面的一些文字描述在代码中具体去看看。

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()

看下直接执行构造函数会有什么结果。

  var str = String();
  var num = Number();
  var bool = Boolean();
  var obj = Object();
  var arr = Array();
  var func = Function();

46-constructor

对象的原型

上文说的对象的原型,在打印的结果中可以发现,就是 __proto__ 属性,原型链的形成靠的就是这个。而 prototype 是函数独有的属性,是保存它们所有实例方法的真正所在,例如常见的 toString()valueOf() 等方法实际上都保存在 prototype 名下。在模仿类的继承特性时 prototype 属性起到了很重要的作用。

Back to top :arrow_up:

参考资料