面向对象、原型、闭包
**闭包:
作用域:一个变量的可用范围
作用域链:记录一个函数,可用作用域的*对象*!
方法定义时:创建2个对象:
1个对象:保存方法体的方法对象
2个对象:当前方法的作用域链对象
作用域链对象中有一个元素指向全局对象
方法调用过程中:创建1个对象,作用域链中多出一个新元素
1个对象:创建该方法*本次调用*的*活动对象*
活动对象中保存了*本次调用*的局部变量
如果方法定义中没有局部变量,活动对象中不会包含任何变量
作用域链中新追加的元素,引用了活动对象
方法调用结束后:作用域链中的新元素出栈
活动对象无人使用,自动回收释放
***闭包:
为什么用闭包:全局变量可共享,但容易被污染
局部变量虽然私有,但不可重用/共享
解决:3步:1. 用大的方法将变量和操作变量的方法封装起来
2. 在外层方法结尾,将操作变量的方法对象返回
3. 在全局,使用专门的方法名接住外层方法返回的函数对象
何时使用闭包:保护可反复使用的局部变量
判断闭包:3特点:
1. 方法嵌套;
2. 内层方法使用了外层方法的局部变量
3. 内层方法被外层方法返回到外部,被反复调用。
1. 面向对象:
1. 创建对象:3种方式
2. 原型:
3. 继承:
1. 创建自定义对象:
对象:专门描述现实中一个东西的属性和功能的程序结构
对象中封装了一个东西的属性以及对属性的操作方法
如何创建:3种方式:
1. 对象直接量的方式:
var obj={属性名:属性值,
... ...}
***js中对象的本质,其实是关联数组/Hash数组
存入属性时,以hash算法,根据属性名计算存储位置
读取属性时,以hash算法,快速算出存储位置,直接读取
***hash数组优点:极快的查找速度。与数据量无关。
对象中的方法内,访问对象自己的属性:this.属性名
this.读作“当前对象的”
3. 使用对象模板/构造函数创建对象:
何时使用:使用统一的数据结构,反复创建多个对象
构造函数作用:2个:
1. 接收要封装到对象中的属性值
2. 用接收到的属性值,初始化对象的属性
如何使用:2步:
1. 先定义统一的对象结构/构造函数
function 构造函数名(参数1,参数2,....){
this.属性1=参数1;
this.属性2=参数2;
this.方法名=function(){......}
}
其中,this表示当前正在创建的对象
2. 使用new关键字,调用构造函数创建对象
var obj=new 构造函数名(参数值1,参数值2,...);
1. new 创建一个对象
2. 按构造函数的规定,初始化对象中的属性
3. ?
4. 将新对象的地址,存入等号左边的变量中
. this:用在函数内,指代当前正在调用方法的对象。
*this和定义时的对象无关。仅和调用时的对象有关*
面向对象三大特点:封装,继承,多态
封装:对象内封装了描述一个事物的属性和方法
多态:同一个对象,可以表现出不同的状态
继承:子对象可以使用父对象中的属性和方法
2. 原型:集中存储多个对象共用的属性值和方法的父对象
每个函数都有一个prototype属性指向自己的原型对象
何时使用构造函数的原型?
多个对象共用的属性值和方法,都要放在原型中。
一次创建,反复使用。
如何向原型中添加属性和方法:
构造函数名.prototype.共享属性名=属性值
构造函数名.prototype.共享方法名=function(){...}
为对象扩展属性:
1. 自有属性:通过对象的引用添加的属性;
其它对象无法访问。
2. 原型属性:通过原型对象添加的属性;
所有继承自原型的子对象都可以访问
获得对象的原型:2种
1. 通过构造函数的prototype属性获得
2. 通过Object.getPrototypeOf(obj)获得
检测自有属性和原型属性:
1. 检查在整个原型关系上是否存在某个属性:
var bool="属性名" in 对象
返回true:属性名包含在对象中或
也可能包含在原型对象中
返回false:对象中和原型对象中一定都没有!
2. 检查自有属性:
var bool=obj.hasOwnProperty("属性名")
返回true:对象中包含指定属性名
返回false:仅说明对象中没有,
不能确定原型中是否包含
3. 面向对象:
1. 多态:重写:子对象认为父对象中方法不好用!
可定义自有的同名方法,重写父对象中方法
2. 继承:子对象可以直接使用父对象中的属性和功能
为什么使用继承:代码重用
如何实现继承:
将要继承的父对象,设置为子对象的原型
2种方式:
1. 修改单个对象的原型:
Object.setPrototypeOf(子对象,父对象)
优:任何时候修改任何对象的父对象
缺:每次仅能修改单个对象
2. 批量修改多个对象的原型:
修改构造函数的原型即可!
构造函数.prototype=父对象
创建对象之前!
优:之后创建的所有子对象,自动继承父对象
缺:必须在创建对象之前修改!
2. prototype:存储多个对象共享的属性值或方法的父对象
1. 所有方法都有prototype属性,指向自己的原型对象
2. 所有对象都有__proto__属性,指向自己的父对象
构造函数创建出的对象:
__proto__指向构造函数的prototype对象
使用直接量创建的单个对象:
__proto__指向Object的prototype对象
3. 继承:子对象直接使用父对象的属性和功能。
原型继承:将一个子对象的原型设置为另一个父对象
如何实现继承:
1. 修改单个对象的__proto__属性
Object.setPrototypeOf(子对象,父对象)
2. 批量修改多个对象的原型:
条件:在使用构造函数创建对象前
构造函数.prototype=父对象
var obj=new 构造函数(属性值1,属性值2,...);
1. new 创建新对象
2. 调用构造函数初始化对象中的属性和方法
3. 将对象的__proto__设置为构造函数的原型
4. 将新创建的对象的地址,存入全局变量obj中。