2.8 KiB
在浏览器环境中,我们也无法单纯依靠 JavaScript 代码实现 div 对象,只能靠 document.createElement 来创建,也说明了 JavaScript 的对象机制并非简单的属性集合 + 原型
对象分类
- 宿主对象 (host Object):由 JavaScript 宿主环境提供的对象,它们的行为完全由宿 主环境决定
- 内置对象 (Built-in Objects):由 JavaScript 语言提供的对象
- 固有对象 (Intrinsic Objects):由标准规定,随着 JavaScript 运行时创建而自动创 建的对象实例。
- 原生对象 (Native Objects):可以由用户通过 Array、RegExp 等内置构造器或者特 殊语法创建的对象。
- 普通对象 (Ordinary Objects):由{}语法、Object 构造器或者 class 关键字定义类 创建的对象,它能够被原型继承。
固有对象
固有对象在任何 JS 代码执行钱就已经被创建出来了,它们通常扮演着类似基础库的角色,“类”其实就是固有对象的一种。
固有对象构造器创建的对象多数使用了私有字段,这些字段使得原型继承方法无法正常工作,所以我们可以认为所有这些原生对象都是为了特定能力或者性能而设计出来的 “特权对象”。
函数对象的定义是:具有 call 私有字段的对象,该必须是一个引擎中定义的函数,需要接受 this 值和调用参数,并且会产生域的切换。 构造器对象的定义是:具有 construct 私有字段的对象。
JavaScript 使用对象模拟函数的的设计代替了一般编程语言中的函数,它们可以像其他语言的函数一样被调用、传参,只需要实现了上面函数对象的定义要求,就能被 JavaScript 函数调用语法支持。
用户用 function 关键词创建的函数必定同时是函数和构造器,但是它们表现出来的行为效果却并不相同:比如 Number 、String 等构造器在被当作函数调用时则产生类型转换的效果。在 ES6 之后使用 =>
语法创建出来的函数仅仅是函数,它们无法被当作构造器来使用。
但是对于用户使用 function
语法或者 Function 构造器创建的对象来说,call 和 construct 的行为却是相似的
construct 的执行过程实际上和 new 关键词的执行过程是一致的:
- 创建一个空的简单JavaScript对象 (即 {},以 Object.prototype 为原型)
- 为步骤1新创建的对象添加属性 __proto__,将该属性链接至构造函数的原型对象
- 以新对象为 this,执行函数的 call
- 如果 call 的返回值是对象则返回该对象,否则返回第一步创建的对象
以上也是出现闭包的背景原因,因为如果构造函数返回一个对象,那么步骤一创建的新对象就会变成一个除了构造函数之外完全无法访问的对象。