作用域链:[针对标识符解析]
JS 执行都是在 "执行环境" 中进行的, 最外围是全局执行环境 (浏览器中是 Windows 对象), 当执行流进入一个函数时, 函数的环境会被推入环境栈中, 函数执行完后, 栈将其环境弹出, 把控制权返回给之前的执行环境. 当代码在一个环境中执行时, 会创建 VO(变量) 对象的一个作用域链. 作用域链的用途, 是保证对执行环境有权访问的所有变量和函数的有序访问. 作用域链的前端, 始终都是当前执行代码所在环境的 VO. 如果这个环境是个函数, 则将其 AO(活动对象)作为 VO. 作用域链的下一个 VO 来自包含 (外部) 环境, 以此类推.
标识符解析是沿着作用域链一级一级地搜索标识符的过程. 搜索过程始终从作用域链的前端开始, 然后逐级地向后回溯, 直至找到标识符为止.
延长作用域链:
try-catch 的 catch 语句, with 语句可临时在当前作用域链的前端增加一个 VO
try{ }catch(err){ } 创建一个 VO, 其中包含错误对象
with(o){ } 将指定对象添加到作用域链中
原型链:[针对构造函数]
JavaScript 万物都是对象, 函数创建时有 prototype 属性指向原型对象, 每个对象实例都有__proto__属性指向该对象的构造函数的原型对象. 在 JavaScript 中是通过 prototype 对象指向父类对象, 直到指向 Object 对象为止来实现继承, 这样就形成了一个原型指向的链条, 此为原型链.
对象实例, 构造函数, 原型之间的关系如下:(引用网上的图片)
Object.getPrototypeOf(实例),Object.setPrototypeOf(object,proto) 可操作[[Prototype]]
__proto__也可以获取, mdn 不推荐
注意: 构造函数和对象实例是不发生关系的
__proto__与 prototype 的区别:(引用网上的图片)
解释: b,c 为对象实例, b,c 的__proto__指向其构造函数的原型对象即 Foo.prototype.Foo 为函数实例, 那么 Foo 的__proto__就指向构造一个普通函数的构造函数 (Function) 的原型对象即 Function.prototype.JS 里的本地对象都是有 Object 构造的, 所以 Function.prototype.__proto__指向 Object.prototype.
这里有一点图里没画出来, 就是 Function 又是谁构造出来的呢?
经测试: Function.__proto__ === Function.prototype //true
Function.prototype.__proto__ === Object.prototype //true
来源: http://www.jianshu.com/p/235b38333692