2019-03-29 | 重学前端系列笔记 | UNLOCK

3. 所知道的全部对象类型

宿主对象: 由 JavaScript 宿主环境提供的对象,它们的行为完全由宿主环境决定。

  • JavaScript 可以运行在很多地方,但是跟我们打交道时间最长的就是浏览器。其中浏览器提供了 location ** Window** 、DocumentAPI 都是宿主环境提供的宿主对象。
  • 其中 windowJavaScript** 这门语言。
  • JavaScript 标准中规定了全局对象属性,w3c 的各种标准中规定了 window 对象的其它属性。
  • 宿主对象也分为固有的和用户可创建的两种,比如 document.createElement 就可以创建一些 dom 对象。
  • 浏览器也会提供一些构造器,通过 newDomNew ImageImgDom 对象

内置对象:由 JavaScript 语言提供的对象。

(0)固有对象:由标准规定,随着 JavaScript 运行时创建而自动创建的对象实例。

固有对象在任何 JS 代码执行前就已经被创建出来了,它们通常扮演者类似基础库的角色。我们前面提到的“”其实就是固有对象的一种。

(1)原生对象:可以由用户通过 Array、RegExp 等内置构造器或者特殊语法创建的对象。

原生的对象有:
6cb1df319bbc7c7f948acfdb9ffd99d0.png

在使用这些对象的时候,可以通过 New 关键字创建新对象。

用对象来模拟函数与构造器:函数对象与构造器对象

这类对象具有私有字段 [[call]] 和 [[construct]],其中

  • [[call]] 私有字段必须是一个引擎中定义的函数,需要接受 this 值和调用参数,并且会产生域的切换
  • 任何对象只需要实现 [[call]]函数对象**,可以作为函数去调用
  • 而如果它能实现 [[construct]],它就是一个构造器对象,可以作为构造器被调用。

函数对象调用与构造器调用

1
2
3
4
5
function f(){
return 1;
}
let v = f(); // 把 f 作为函数调用
let o = new f(); // 把 f 作为构造器调用

我们大致的可以理解 **[[construct]] **的执行过程为

  • 以 Object.protoype 为原型创建一个新对象;
  • 以新对象为 this,执行函数的 [[call]];
  • 如果 [[call]] 的返回值是对象,那么,返回这个对象,否则返回第一步创建的新对象。
  • 一定程度上,new创造的对象及属性,构造器之外是无法访问的,在一定程度上可以实现“私有”

对于有 JS 解析引擎的地方,只要字段正常。宿主对象及内置对象也可以模仿函数对象及构造器对象。

1
2
3
4
5
6
7
// 内置对象
let time = new Date;
//或者
let time = Date();
// 宿主对象,在浏览器可以使用Image对象
let img = new Image; // 可以得到一个img Dom对象
let img = Image() //会抛出错误

*注意: ES6语法创建的函数,仅仅是函数,是不能作为构造器使用的

1
new (date=>{}) // error

(2)普通对象:由{}语法、Object 构造器或者 class 关键字定义类创建的对象,它能够被原型继承。

例:

1
2
let Child = (){};
let childItem = new Child

其他

除了上述的对象,有一些对象跟正常的对象有很大的区别,
它们常见的下标运算(就是使用中括号或者点来做属性访问)或者设置原型跟普通对象不同

  • ArrayArraylength 属性根据最大的下标自动发生变化。
  • Object.prototype :作为所有正常对象的默认原型,不能再给它设置原型了。
  • StringString** 的正整数属性访问会去字符串里查找。
  • Argumentsarguments** 的非负整数型下标属性跟对应的变量联动。
  • 模块的 namespace 对象:特殊的地方非常多,跟一般对象完全不一样,尽量只用于 import 吧。
  • 类型数组和数组缓冲区:跟内存块相关联,下标运算比较特殊。
  • bindfunction** :跟原来的函数相关联。

评论加载中