闭包和继承
闭包
回顾作用域
函数的上级作用域在哪里创建创建的,上级作用域就是谁
js
var a = 10
function foo(){
console.log(a); // 10
}
function sum() {
var a = 20
foo()
}
sum()
console.log(a); // 10
//函数 foo() 是在全局下创建的,所以 a 的上级作用域就是 window,输出就是 10JS 堆栈内存释放
- 堆内存:存储引用类型值,对象类型就是键值对,函数就是代码字符串。
- 堆内存释放:将引用类型的空间地址变量赋值成
null,或没有变量占用堆内存了浏览器就会释放掉这个地址 - 栈内存:提供代码执行的环境和存储基本类型值。
- 栈内存释放:一般当函数执行完后函数的私有作用域就会被释放掉。
但栈内存的释放也有特殊情况:
函数执行完,但是函数的私有作用域内有内容被栈外的变量还在使用的,栈内存就不能释放里面的基本值也就不会被释放。
全局下的栈内存只有页面被关闭的时候才会被释放
闭包是什么
闭包是指有权访问另一个函数作用域中变量的函数
本质就是上级作用域内变量的生命周期,因为被下级作用域内引用,而没有被释放。就导致上级作用域内的变量,等到下级作用域执行完以后才正常得到释放。
举个栗子
js
var n = 10
function fn(){
var n =20
return function f() {
n++;
console.log(n)
}
}
var x = fn()
x()形成闭包的原因
内部的函数存在外部作用域的引用就会导致闭包
闭包的特点
闭包的优点
- 能够让函数外部访问到函数内部的私有变量
- 能够保护函数的私有变量,不会污染全局=
- 可以利用闭包的特性,缓存数据,提升代码性能
闭包的缺点
- 因为对数据的持续引用,导致函数的执行空间不销毁,容易造成内存泄露
解决闭包造成内存泄露的问题
- 在使用完成之后,给变量赋值为null,这样内存就会释放了
GC机制
GC(Garbage Collection),js有一套自己的内存管理机制,叫做垃圾回收机制,当一些变量或者函数在使用完成之后,GC这个算法会自动释放内存,来优化提升js执行的性能
闭包不会被GC机制回收,循环应用会导致内存泄露,怎么解决这个问题?(面试题)
- 闭包使用完成之后,主动释放内存,赋值为null直接就释放了
js
var n = 10
function fn(){
var n =20
return function f() {
n++;
console.log(n)
}
}
var x = fn()
x()
x()
x()
x = null; //直接释放了内存,fn就不会被持续占用了继承
面向对象的三大特性: 封装、继承、多态
- 继承是和构造函数相关的一个应用
- 是指,让一个构造函数去继承另一个构造函数的属性和方法
- 所以继承一定出现在 两个构造函数之间
常见的继承方式
我们有一些常见的继承方式来实现和达到继承的效果
我们先准备一个父类(也就是要让别的构造函数使用我这个构造函数的属性和方法)
javascriptfunction Person() { this.name = 'Jack' } Person.prototype.sayHi = function () { cosnole.log('hello') }这个
Person构造函数为父类让其他的构造函数来继承他
当别的构造函数能够使用他的属性和方法的时候,就达到了继承的效果
原型继承
原型继承,就是在本身的原型链上加一层结构
javascript
function Student() {}
Student.prototype = new Person()借用构造函数继承
把父类构造函数体借用过来使用一下而已
javascript
function Student() {
Person.call(this)
}组合继承
就是把 原型继承 和 借用构造函数继承 两个方式组合在一起
javascript
function Student() {
Person.call(this)
}
Student.prototype = new Person
Student.prototype.constructor = Student