闭包是什么? 简单来说 就是 一个函数里面, 返回另一个函数。
闭包的作用:
1.延长变量存在的周期
2.创建独立的作用域
作为js的三大核心之一,闭包是什么呢?闭包就是函数执行时依赖变量作用域,而这个作用域是在函数定义时决定的,而不是函数调用时决定的,简单来说,就是闭包这个特性,在外部函数可以访问到局部函数的作用域,好啦,话不多少,下面请看例子.
// 下面的这段代码 我相信你们能看懂
var name = "张三";
function getName () {
var name = "李四";
function f () {
return name;
}
return f();
}
getName (); // "李四"
// 接下来 这段代码呢 你就明白了 我上面为什么这么说了
var name = "张三";
function getName () {
var name = "李四";
function f () {
return name;
}
return f;
}
var user = getName ();
user(); // 这个结果是什么呢
// 什么 居然也是 "李四",不是 "张三", 没错上面 已经解释的很清楚了
闭包就是函数执行时依赖变量作用域,而这个作用域是在函数定义时决定的,而不是函数调用时决定的,所以返回的结果 还是 "李四"
有一点头绪之后 我们来看一下,下面这段程序吧
function funConst () {
var arr = [];
for (var i=0; i< 10; i++) {
arr[i] = function () {
return i;
}
}
return arr;
}
var aaa = funConst();
aaa[5](); // 结果是什么呢? 10
卧槽,居然是10,怎么回事,小老弟,这跟我们想要的结果完全不一样啊,发生了什么...
因为他们在同一个函数里面调用的,所以他们可以共享变量,当程序执行完了之后,i的值变成了10,所以说数组里面的所有值都是10
那这个怎么变成我们想要的呢
function funConst () {
var arr = [];
for (var i=0; i< 10; i++) {
arr[i] = function (num) {
return function () {
return num;
}
}(i)
}
return arr;
}
var aaa = funConst();
aaa[5](); // 那么这个结果是什么呢 5
哇,好神奇,结果变成了我们想要的样子了, 这个是什么原理呢,我们利用了闭包,把i作为一个变量传给了一个函数,那么函数里面的num就是他的局部变量了,然后把这个num返回回来,他们就有各自的作用域,而不会相互影响.
其实 还有一种实现方法,就是es6里面的let变量,它本身就是块级作用域
function funConst () {
let arr = [];
for (let i=0; i< 10; i++) {
arr[i] = function () {
return i;
}
}
return arr;
}
let aaa = funConst();
aaa[5](); // 结果也是 5
接下来 我们来看看 下一个例子,你就会更加的熟悉一些了
var name = "张三";
var obj = {
name: "李四",
getName: function () {
return function () {
return this.name;
}
}
};
obj.getName()(); // 这个结果是什么呢 => "张三"
为什么会是张三呢, 因为,每个函数被调用时,活动变量都会拿到 this 和 arguments ,内部函数在搜索这两个变量时,只会搜索到活动对象位置,因此永远也不可能直接访问到函数的这两个变量
那我们 非要拿到对量里面的李四怎么办呢,在函数外给他增加this,拿到当前this的作用域
var name = "张三";
var obj = {
name: "李四",
getName: function () {
var _this = this;
return function () {
return _this .name;
}
}
};
obj.getName()(); // 结果就是 李四啦
有些人可能会说,请看下面的代码
var name = "张三";
var obj = {
name: "李四",
getName: function () {
return this.name;
}
};
obj.getName(); // 结果也是 李四
这个是当然的呀,因为 在 obj中 this.name 本来就是 李四
当然我们也可以通过call 和 apply来改变函数的作用域
function name() {
return this.name
}
var obj = {
name: "张三"
};
name.call(obj); // 结果是 "张三"
我们的apply用法
var list = [1,5,3,2];
Math.max.apply(this, list) // apply的第二个参数是必须传入数组
使用闭包的好处,还有一个就是不污染 全局作用域, 例如 当我们做程序开发的时候,不同的人,难免会出现相同的定义,导致程序 出现一些不好维护的问题
function count (num) {
for (var i=0; i<num; i++) {
console.log(i);
}
console.log(i); // 计数 这里拿到的值是 5,很明显这被污染了
}
count(5);
我们 通过闭包的方式
function count (num) {
(
for (var i=0; i<num; i++) {
console.log(i);
}
)()
console.log(i); // 导致一个错误, 这样子 就不会影响我们下面的变量了
}
count(5);
// 创建独立的作用域
// let a= "小明";
// function fn() {
// let b = "小胡";
// console.log(a);
// }
// fn();
function makerCount() {
// 初始化值
let num = 0;
// 执行方法
function change(val) {
num += val;
}
// 这里是返回给 你要想要暴露出去的值
return {
add: function() {
change(1);
},
reduce: function() {
change(-1);
},
getValue: function() {
return num;
}
}
}
let makerCount1 = makerCount();
let makerCount2 = makerCount();
makerCount1.add();
makerCount1.add();
makerCount2.add();
console.log(makerCount1.getValue(), "makerCount1");
console.log(makerCount2.getValue(), "makerCount2");
我知道的闭包的大概用法就在这里了,如果有什么问题,欢迎指出.