每当控制器到达ECMAScript可执行代码的时候,控制器就进入了一个执行上下文.
执行上下文是个抽象概念,标准中没有从技术实现上定义执行上下文的具体结构和类型.
就是一系列活动的执行上下文从逻辑上形成一个栈(比较抽象).
栈底总是全局上下文,栈顶是当前(活动的)执行上下文.
当在不同的执行上下文间切换(退出而进入新的执行上下文)的时候,栈会被修改(通过压栈或者出栈的形式).
变量对象
执行上下文的数据是以变量对象的属性形式进行存储的.
一个变量对象(简写为VO)是一个和执行上下文相关的特别对象,存储以下内容:
变量(声明的变量,var)
函数声明(简写为FD)
在上下文中,函数声明的形式参数
作用域链
作用域链是一条变量对象的链,它和执行上下文有关,用于在处理标识符的时候进行变量查询.
函数上下文的作用域链在函数调用的时候创建出来,它包含了活跃对象和该函数的内部[[Scope]]属性.
执行上下文变量大致如下:
activeExecutionContext = {
VO:{...},//或者AO
this:thisValue,
Scope:[
//作用域链,所有变量对象的列表,用来查询标识符
]
}
上面Scope可以定义如下:
Scope = AO+[[Scope]]
可以用数组进行表示:
var Scope = [VO1,VO2,...,VOn]//作用域链
Object() Function() Array() 等等都为构造函数。
Js 面向对象与传统oop 有些不同,语法较高级 语法糖封装。
This 为指针。指向this作用域的调用者
1.原型继承链顶端为Object 。Js函数是对象
2.当读取对象中的属性时,先去实例本身中搜索,如搜索不到则去指向的原型中搜索
1.原型的存在意义在于实现继承共享,是在构造函数中定义的一个成员对象,在下次实例化时不需要在构造函数中定义成员 就可实现实例共享方法属性。
例子:通常为。构造函数.prototype.xxx=我想实现实例继承的东西 -》 new 构造函数 -》新实例a对象.原型指针指向构造函数的xxx对象(引用类型)
例子:Array 不等于 Array() 原因 Array为一个函数,而Array()为一个构造函数调用语句,故Array拥有prototype对象用于实例的共享继承,Array()产生一个实例 故只能拥有prototype对象的私有指针 proto
2.在使用原型继承时 不能使用字面量 构造函数.prototype={} 的方式重写原型对象 。因为会导致该原型对象的constructor属性被重写,在生成的实例中导致constructor指向Object并且会切断之前原型对象的联系,破坏原型链。
3.JavaScript 主要通过原型链实现继承。原型链的构建是通过将一个类型的实例赋值给另一个构造函数的原型实现的
例子:
xxx实例. proto -》function xxx()构造函数.prototype对象故xxx. proto === xxx.prototype
xxx.prototype. proto -》Object.prototype因为所有对象都为Object函数构造来的。故xxx.prototype. proto ===Object.prototype。
Object.prototype. proto 为原型链顶端 proto 定义了尚未使用所以为null故Object.prototype. proto ===null约定俗成。
instanceof 用来判断某实例是否为某构造函数的实例
isPrototypeOf 用于判断某实例是否拥有某构造函数的原型对象指针
1.原型模式有忽略构造函数定义初始值步骤及原型中操作引用类型的缺点。
所以需要组合使用 构造函数模式+原型模式 来创建实例。在构造函数中定义实例的属性,而需共享的方法就定义在原型对象中。
继承:在子构造函数中调用 父.call(this, name)实现构造函数之间的属性继承。使用 子.prototype = new 父()子.prototype.constructor = 子实现方法的继承。
2.如要在生产环境下的构造函数新增方法(如Array) 需要使用一个类似于工厂函数的寄生构造函数模式 在构造函数中返回一个修改后的对象