闭包
闭包的基本概念
闭包(closure)是JavaScript的一个特色,很多高级的应用都要依靠闭包来实现。
作用域
在js中,函数会形成函数作用域,在函数内部可以直接访问全局变量
1 | var str = "zs"; |
在函数外部却无法访问函数内部的变量
1 | function fn(){ |
问题:怎么才能获取到函数内部的变量?
作用域链
在函数内部有一个函数,那么函数内部的函数是可以访问到外部函数的变量的。
解决方法:
1 | function fn(){ |
在上述代码中,fn中定义的所有变量,对于f2函数都来都是可以访问的。但是现在f2在函数的内部,我们如何在外部访问到f2这个函数呢?
1 | function fn(){ |
闭包的概念
闭包是函数和声明该函数的词法环境的组合。
在JavaScript中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,产生闭包。
**闭包中包含了内部函数的代码,以及所需外部函数中的变量的引用 **
产生闭包的条件
1 | 当内部函数访问了外部函数的变量的时候,就会形成闭包。 |
闭包的作用:
- 私有变量,保护数据安全
- 持久化维持数据
闭包的应用
计数器
需求:统计一个函数的调用次数
1 | var count = 0; |
缺点:count是全局变量,不安全。
使用闭包解决这个问题
1 | function outer(){ |
缓存
缓存(cache):数据的缓冲区,当要读取数据时,先从缓冲中获取数据,如果找到了,直接获取,如果找不到,重新去请求数据。
计算斐波那契数列,会有很大的性能问题,因为重复的计算了很多次,因此我们可以使用缓存来解决这个性能问题。
初级优化:
使用缓存的基本步骤:
- 如果要获取数据,先查询缓存,如果有就直接使用
- 如果没有,就进行计算,并且将计算后的结果放到缓存中,方便下次使用。
1 | // 缓存 |
缺点:既然使用缓存,就需要保证缓存的数据的安全,不能被别人修改,因此,需要使用闭包来实现缓存的私有化。
1 | function outer() { |
闭包存在的问题
闭包占用的内存是不会被释放的,因此,如果滥用闭包,会造成内存泄漏的问题。闭包很强大,但是只有在必须使用闭包的时候才使用。
js的垃圾回收机制
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Memory_Management
- 内存:计算机中所有程序的运行都是在
内存中进行的,因此内存的性能对计算机的影响非常大,运行程序需要消耗内存,当程序结束时,内存会得到释放。 - javascript分配内存:当我们定义变量,javascript需要分配内存存储数据。无论是值类型或者是引用类型,都需要存储在内存中。
- 垃圾回收:当代码执行结束,分配的内存已经不需要了,这时候需要将内存进行回收,在javascript语言中,垃圾回收机器会帮我们回收不再需要使用的内存。
引用记数法清除
引用记数垃圾收集:如果没有引用指向某个对象(或者是函数作用域),那么这个对象或者函数作用域就会被垃圾回收机制回收。
1 | var o = { |
标记清除法清除
使用引用计数法进行垃圾回收的时候,会出现循环引用导致内存泄漏的问题。因此现代的浏览器都采用标记清除法来进行垃圾回收。
这个算法假定设置一个叫做根(root)的对象(在Javascript里,根是全局对象Window)。定期的,垃圾回收器将从根开始,找所有从根开始引用的对象,然后找这些对象引用的对象……从根开始,垃圾回收器将找到所有可以获得的对象和所有不能获得的对象。
从2012年起,所有现代浏览器都使用了标记-清除垃圾回收算法。
闭包占用内存释放
1 | function outer(){ |
正则表达式
正则表达式:用于匹配规律规则的表达式,正则表达式最初是科学家对人类神经系统的工作原理的早期研究,现在在编程语言中有广泛的应用,经常用于表单校验,高级搜索等。
创建正则表达式
构造函数的方式
1 | var regExp = new RegExp(/\d/); |
正则字面量
1 | var regExp = /\d/; |
正则的使用
1 | /\d/.test("aaa1"); // 返回布尔值 |
元字符
正则表达式由一些普通字符和元字符组成,普通字符包括大小写字母、数字等,而元字符则具有特殊的含义。
常见元字符
|表示或,优先级最低
()优先级最高,表示分组
字符类的元字符
[]在正则表达式中表示一个字符的位置,[]里面写这个位置可以出现的字符。
1 | console.log(/[abc]/);//匹配a,b,c |
[^]在中扩号中的^表示非的意思。
1 | //^表示该位置不可以出现的字符 |
[a-z] [1-9]表示范围
1 | console.log(/[a-z]/.test("d"));//小写字母 |
边界类元字符
前面的正则只要有满足的条件的就会返回true,并不能做到精确的匹配。
^表示开头 []里面的^表示取反
$表示结尾
1 | console.log(/^chuan/.test("dachuan"));//必须以chuan开头 |
量词类元字符
量词用来控制出现的次数,一般来说量词和边界会一起使用
*表示能够出现0次或者更多次,x>=0;+表示能够出现1次或者多次,x>=1?表示能够出现0次或者1次,x=0或者x=1{n}表示能够出现n次{n,}表示能够出现n次或者n次以上{n,m}表示能够出现n-m次
