闭包
一、函数复习
1.1函数的定义和调用
1.1.1 函数的定义方式
方式1: 函数声明方式 function fn(){}
方式2: 函数表达式(匿名函数) var fn = function(){}
方式3:new Function() var fn = new Function (‘参数1’,‘参数2’…,‘函数体’)
● 注意 Function 里面参数都必须是字符串格式
● 第三种方式执行效率低,也不方便书写,因此较少使用
● 所有函数都是 Function 的实例(对象)
● 函数也属于对象
1.1.2函数的调用
普通函数的调用 —> 直接调用
function fn(){
console.log('人生的巅峰');
}
fn();
对象的方法 —> 对象调用
var o = {
sayHi: function(){
console.log('人生的巅峰');
}
}
o.sayHi()
构造函数 —> new 调用
function Star(name,age) {
this.name = name;
this.age = age;
};
new Star ();
立即执行函数(IIFE)
var x = 1;
(function(y){
console.log(y);
})(x)
二、高阶函数
高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。
1.接收函数作为参数 —> 回调函数
2.函数作为返回值输出
2.1 变量作用域复习
变量根据作用域的不同分为两种: 全局变量和局部变量。
函数内部可以使用全局函数
函数外部不可以使用全局函数
当局部函数执行完毕,本作用域内的局部变量会销毁。
问:如何从外部读取局部变量?
出于种种原因,我们有时候需要得到函数内的局部变量。但是前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。
那就是在函数的内部,在定义一个函数。
function f1 (){
var n = 999;
function f2(){
alert(n);//999
}
f2();
}
f1();
2.2 什么是闭包
闭包(closure)指有权访问另一个函数作用域中变量的函数。(官方说法)
简单理解就是:定义在一个函数内部的,它可以访问到外部函数的局部变量
function init() {
var name = "Mozilla"; // name 是一个被 init 创建的局部变量
function displayName() { // displayName() 是内部函数,一个闭包
alert(name); // 使用了父函数中声明的变量
}
displayName();
}
init();
看重点:displayName() 没有自己的局部变量。
然而,因为它可以访问到外部函数的变量,所以 displayName() 可以使用父函数 init() 中声明的变量 name 。
在一些编程语言中,一个函数中的局部变量仅存在于此函数的执行期间。
一旦 init() 执行完毕,你可能会 认为 name 变量将不能再被访问。
2.3 闭包的特点
闭包的特点:函数A嵌套函数B,函数B能访问函数A的变量,函数B就是闭包
常见的闭包写法:函数A嵌套函数B , 函数B能访问函数A的变量 , 并返回函数B
1、闭包就是可以读取函数内部的变量的函数
2、闭包让我们能够从一个函数内部访问其外部函数的作用域
3、让变量的值始终保持在内存中
闭包的经典案例:
function foo() {
var local = 1
function bar() {
return ++local
}
return bar
}
var func = foo()
console.log(func());
2.4 案例讲解-点击li输出索引号
for (var i = 0; i < lis.length; i++) { // 利用for循环创建了4个立即执行函数 // 立即执行函数也成为小闭包因为立即执行函数里面的任何一个函数都可以使用它的i这变量
(function(i) {
lis[i].onclick = function() {
console.log(i);
}
})(i);
}
2.5 案例讲解-定时器中的闭包
for (var i = 0; i < lis.length; i++) {
(function(i) {
setTimeout(function() {
console.log(lis[i].innerHTML);
}, 3000) })(i);
}
2.6 例题
function foo() {
var i = 0;
return function () {
console.log(i++);
}
}
var f1 = foo();
var f2 = foo();
f1();
f1();
f1();
f1();
f2();
f2();
f2();
f2();
f2();
2.7 闭包的优缺点
当函数执行完毕,本作用域内的局部变量会被销毁。
闭包的优点:
● 让这些变量一直存在于内存中,不会在调用结束后,被垃圾 回收机制回收 (如果多了就成了缺点)
● 避免全局变量污染
● 私有化变量
闭包的缺点:
● 由于闭包会使函数中的变量保存在内存中,内存消耗很大,所以不能滥用闭包
● 容易引起内存泄漏