原型和原型链
- 所有对象都是通过
new 函数
创建 - 所有的函数也是对象
- 函数中可以有属性
- 所有对象都是引用类型
原型 prototype
所有函数都有一个属性:prototype,称之为函数原型。
默认情况下,prototype 是一个普通的 Object 对象。
默认情况下,prototype 中有一个属性,constructor,它也是一个对象,它指向构造函数本身。
隐式原型 proto
所有的对象都有一个属性:__proto__
,称之为隐式原型
默认情况下,隐式原型指向创建该对象的函数的原型。
当访问一个对象的成员时:
- 看该对象自身是否拥有该成员,如果有直接使用
- 在原型链中依次查找是否拥有该成员,如果有直接使用
猴子补丁:在函数原型中加入成员,以增强起对象的功能,猴子补丁会导致原型污染,使用需谨慎。
原型链
特殊点:
- Function的__proto__指向自身的prototype
- Object的prototype的__proto__指向null
执行上下文
函数执行上下文:一个函数运行之前,创建的一块内存空间,空间中包含有该函数执行所需要的数据,为该函数执行提供支持。
执行上下文栈:call stack,所有执行上下文组成的内存空间。
全局执行上下文:所有 JS 代码执行之前,都必须有该环境。
JS 引擎始终执行的是栈顶的上下文。
执行上下文与作用域不同:
- 作用域是静态的,函数定义时就确定
- 执行上下文是动态的,当函数运行时才确定
执行上下文中的内容
-
首先确定 this 指向
1). 直接调用函数,this指向全局对象
2). 在函数外,this指向全局对象
3). 通过对象调用或new一个函数,this指向调用的对象或新对象 -
然后确定 VO 变量对象
Variable Object:VO 中记录了该环境中所有声明的【参数】、【变量】和【函数】
Global Object: GO,全局执行上下文中的VO
Active Object:AO,当前正在执行的上下文中的VO1). 确定所有形参值以及特殊变量 arguments
2). 确定函数中通过 var 声明的变量,将它们的值设置为 undefined,如果 VO 中已有该名称,则直接 忽略。
3). 确定函数中通过字面量声明的函数(直接通过 function 声明),将它们的值设置为指向函数对象,如果 VO 中已存在该名称,则覆盖。
当一个上下文中的代码执行的时候,如果上下文中不存在某个属性,则会从之前的上下文寻找。
作用域链
- VO 中包含一个额外的属性,该属性指向创建该 VO 的函数本身。
- 每个函数在创建时,会有一个隐藏属性
[[scope]]
,它指向创建该函数时的 AO。 - 当访问一个变量时,会先查找自身 VO 中是否存在,如果不存在,则依次查找
[[scope]]
属性。
某些浏览器会优化作用域链,函数的[[scope]]
中仅保留需要用到的数据。
事件循环
异步:某些函数不会立即执行,需要等到某个时机成熟后才会执行,该函数叫做异步函数。
浏览器的线程:
- JS 执行引擎:负责执行 JS 代码
- 渲染线程:负责渲染页面
- 计时器线程:负责计时
- 事件监听线程:负责监听事件
- http 网络线程:负责网络通信
事件队列:具体体现为一块内存空间,用于存放执行时机到达的异步函数。当 JS 引擎空闲(执行栈没有可执行的上下文),它会从事件队列中拿出第一个函数执行。
事件循环(event loop):是指函数在执行栈、宿主线程、事件队列中的循环移动。