闭包&作用域
理解闭包
闭包是指 有权访问另一个函数作用域中的变量的 函数,闭包是定义在一个函数内部的函数
1 | documnt.body.innerHTML = "<div id=div1>aaa</div>"+ |
** 变量的作用域 **
- 函数内部可以直接读取全局变量。
- 函数外部自然无法读取函数内的局部变量。
- 函数内部声明变量,一定要使用var命令。如果不用,你实际上声明了一个全局变量!
** 如何从外部读取局部变量?**
Javascript语言特有的”链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
** 闭包的用途 **
- 可以读取函数内部的变量
- 让这些变量的值始终保持在内存中。
1 | function f1(){ |
闭包的注意点
- 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
- 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
作用域
全局、函数、eval 三个作用域 没有块级作用域
ES3 执行上下文
JS解释器如何找到我们定义的函数和变量?
- 变量对象(Variable Object,VO) 是有一个抽象概念中的“对象”,它用于存储执行上下文中的:1. 变量 2. 函数声明 3. 函数参数
JS解释器初始化 VO上下文
1 | VO(globalContext) === [[global]]; |
函数中的激活对象 AO
1 | VO(functionContext) === AO; |
VO按照如下顺序填充
1. 函数参数(若为传入 ,初始化该参数值为undefined)
2. 函数声明(若发生命名冲突,会覆盖)
3. 变量声明(初始化变量值为undefined,若发生命名冲突,会忽略。)
1 | function test(a,b){ |
/ | 函数声明 | 函数表达式 | 函数构造器 |
---|---|---|---|
前置 | ✔ | ||
允许匿名 | ✔ | ✔ | |
立即调用 | ✔ | ✔ | |
通过函数名访问 | ✔ | ||
没有函数名 | ✔ |
OOP
概念与继承
封装、继承、多态、抽象
1 | function Foo(){} |
1 | function Person(name,age){ |
原型链如下图
*并不是所有的函数都会继承至Object.prototype *var o = new Obejct(null)
o.__proto__; //undefined
prototype属性
1 | Student.prototype.x = 101; |
instanceof
- 左边一般要求是一个对象,右边要求是一个函数或者说是构造器,它会判断右边构造器的prototype的属性是否出现在左边对象的原型链上。
- 所有右边必须是一个函数对象,不是函数的话 就没有prototype属性 就会报错。
1
2[1,2] instanceof Array === true
new Obejct() instanceof Array === false
实现继承的多种方式
1 | function Person(){} |