本文只是先让自己对这3个东西有个概念上的理解而已。深入理解还要再看书
作用域链(scope chain)
- 作用域链与变量对象有着密不可分的关系,因为作用域链就是变量对象的数组。其中第一个是当前函数的活动对象,第二个是当前活动函数的父亲的上下文的活动对象,第三个是当前活动函数的爷爷的上下文的活动对象。。。最后一个是全局执行环境变量对象(window)。
- 作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终是当前执行的代码所在的环境的变量对象。如果这个环境是函数,则将其活动对象作为变量对象。作用域链中的下一个变量对象来自包含(外部)环境,而再下一个变量对象则来自下一个包含环境。这样,一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链的最后一个对象。
- 举个例子:
1 | var temp1; |
- 由例子可知,内部环境可以通过作用域链访问所有外部环境,但外部环境不能访问内部环境中的任何变量和函数。这些环境之间的联系是线性的、有次序的。每个环境可以向上搜索作用域链,以查询变量和函数名;但任何环境都不能通过向下搜索作用域链而进入另一个执行环境。
闭包
闭包是指那些能访问外部作用域中声明变量的函数。
闭包的应用
柯里化
利用闭包保存和收集所有参数。
1 | function add(){ |
模块化
封装私有变量,向外暴露接口。
一道关于闭包的经典面试题
1 |
|
原型与原型链
原型
原型:每一个Javascript对象(null除外),在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型“继承”属性。
prototype
:每个函数都有一个prototype属性。函数的prototype指向了一个对象,这个对象正是调用该构造函数而创建的实例的原型。
1 | function Person() { |
__proto__
:这是每个javascript对象(除了null)都具有的一个属性,这个属性会指向对象的原型。
1 | console.log(person.__proto__ === Person.prototype); // true |
constructor
:每个原型都有一个constructor属性,这个属性只想与之关联的构造函数。
1 | console.log(Person === Person.prototype.constructor); // true |
实例与原型:当读取实例的属性时,如果找不到,就会查找与对象相关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到顶层为止。其实原型对象就是通过 Object 构造函数生成的,结合之前所讲,实例的 __proto__
指向构造函数的 prototype 。
1 | function Person() { |
原型链:
原型链的顶层是null。
1 | console.log(Object.prototype.__proto__ === null) // true |
图中由相互关联的原型组成的链状结构就是原型链,也就是蓝色的这条线。