闭包
定义&原理
闭包即一个拥有许多变量和绑定了这些变量的环境的表达式(通常为函数)
闭包利用了变量的作用域链,函数内部可以访问外部的变量和全局变量,而函数外部无法访问函数内部变量
因此,在函数内部定义一个函数,用函数内的函数来访问函数内部的变量,并将该变量存储在内存中
如下的例子中,因为n相对于f2是全局变量,f2依存于f1,因此运行a(实际为f1)之后,n继续保存在内存中不清除
执行nAdd函数后,n变成1000
1 function f1(){ 2 var n = 999; 3 nAdd = function(){ 4 n = n+1; 5 } 6 function f2(){ 7 alert(n); 8 } 9 return f2; 10 } 11 var a = f1(); 12 a();//弹出999 13 nAdd(); 14 a();//弹出1000
用途
利用闭包,在函数外读取函数内部的局部变量,并让函数内部的局部变量保存在内存中
优缺点
优点:封装性强,可访问局部变量
缺点:局部变量长时间占用内存,容易产生内存泄漏
封装
定义&原理
把对象内部数据和操作细节隐藏,只对外提供一个对象的专门访问的接口
JS中,利用闭包来实现封装的效果
用函数内的嵌套函数实现访问函数局部变量的方法,叫做特权方法
1 function f1(){ 2 var n = 1; 3 //此处f2函数可以让用户在函数外访问n,为特权方法 4 this.f2 = function(){ 5 console.log(++n); 6 } 7 //等同于下面的方法 8 function f2(){ 9 console.log(++n); 10 } 11 return f2; 12 } 13 var a = f1(); 14 a();
缺点
封装占用了内存,不利于继承
继承
原型
即用prototype给对象添加属性和方法
原型链
JS创建对象时,新对象内部有一个__proto__内置属性,指向创建其函数对象的原型对象prototype
当使用对象的方法时,现在当前对象中查找,如果有则使用,没有就查找当前对象的__proto__属性中是否有方法,有则调用,无则继续向上查找,如此形成一条原型链
原型继承
通过原型方法创建新对象时,如果子对象没有修改/重新定义同名方法,原型中有的方法会继承到子对象中
子对象使用方法时也会沿着原型链逐步向上查找,只有在最顶层父元素都没有该方法时才报错
构造继承
在子类内部构造父类的对象实现继承