***************************为什么要学习闭包*********************
// 变量? 向【内存】中申请的一块空间
// 变量的生命周期:变量从产生到释放的过程。
// 全局变量:程序关闭时,全局变量会被释放。
// 局部变量:在函数调用执行结束后,会被释放。
// GC(Garbage Collection)→ 垃圾回收机制→ 生活中保洁→清理没有用的数据。
var a = 123;
function fn() {
// var b;
console.log(a);//123
console.log('函数开始')
var b = 456;
console.log(b);
console.log('函数结束')
}
fn(); // 函数内部→ 开始→ 创建了变量b→使用了变量b→结束→ 释放了变量b
// fn(); // 函数内部→ 开始→ 创建了变量b→使用了变量b→结束→ 释放了变量b
// fn(); // 函数内部→ 开始→ 创建了变量b→使用了变量b→结束→ 释放了变量b
// console.log(b); // 报错
// 为什么外部无法访问内部的局部变量?
// ① 作用域的规则
// ② 变量没有创建或者被释放
**********************************作用域链*****************************
// 作用域链:
function fn() {
var a = 1, b = 2;
function fn1() {
var b = 22, c = 33;
function fn2() {
var a = 100;
console.log(a, b, c);
}
fn2();
}
fn1();
}
fn();
// 作用域链:访问变量的过程。 从内向外。
// 反之不行。
// console.log(a,b,c);//报错
// 需求:在外部可以操作(间距)到内部的变量。
// 要保证内部的变量不会被释放(延长局部变量的生命周期),并且变量已经被创建。
// 实现技巧:闭包!
************************************如何实现闭包*****************************
function fn() {
var a = 123; // 局部变量
// console.log(a)
// 子函数→卧底
function son () {
console.log('更改之前:' + a);
a = a + 10;
console.log('更改之后:' + a);
}
// 返回
return son; // 将内部函数的地址返回
}
var cyqz = fn();
cyqz();
// cyqz();
// cyqz();
// a不要被释放,每次对a可以实现加减乘除,在a原有值的基础上
*******************************实现闭包的规则*************************
<script>
function fn() {
var a = 123; // 局部变量
return function () {
console.log('更改之前:' + a);
a = a + 10;
console.log('更改之后:' + a);
};
}
var cyqz = fn();
cyqz();
// cyqz();
// cyqz();
// a不要被释放,每次对a可以实现加减乘除,在a原有值的基础上
// 如何检测一个代码中是否存在闭包?
// 【1. 调试:】
// 【2. 规则:】
// ①. 外层函数 和 子函数
// ②. 外层函数必须有局部变量
// ③. 子函数要操作外层函数的局部变量
// ④. 让子函数和外部产生关联。
// 扩展:为什么有了闭包,局部变量没有被释放
// GC回收没有用的数据
// 闭包:外部环境间接操作局部变量,说明局部变量被使用,是有用的数据。
// 闭包的缺点:不当的使用闭包,会造成内存泄露→消耗内存。
// 手动释放:把外部变量设置为null。局部变量会被释放。
// null 空对象
// GC会去回收变量为null内存。
</script>
************************************检测闭包*********************************
// 测试1
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function () {
var a = this;
console.log(a);//Object对象
// 此时的that=this。而this指向object,所以that指向object。
// 无论你执行多少次,他都是对object的引用,所以输出My Object
return function () {
console.log(this.name)//Thewindow
// javascript是动态(或者动态类型)语言,this关键字在执行的时候才能确定是谁。
// 所以this永远指向调用者,即对‘调用对象‘者的引用。
// 第一部分通过代码:object.getNameFunc()调用返回一个函数。这是个返回的函数,
// 它不在是object的属性或者方法,此时调用者是window。因此输出是 The Window
};
}
};
var fn = object.getNameFunc();
fn();
// 你好,谢谢你的回答,但我有个疑问:第一个中不能理解为闭包的第一作用域链是闭包本身,
// 然后是闭包外面的函数,之后是window对象么?它不能像原形链那样一直向上寻找么?
// 追答
// 因为执行代码object.getNameFunc()之后,它返回了一个新的函数,
// 注意这个函数对象跟object不是一个了,可以理解为全局函数。
// 所以它的name属性不会是My Object。这个例子只能作为关键字this的教材。
// 如果作为寻找变量的例子就不好了
// 测试2
// var name = "The Window";
// var object = {
// name: "My Object",
// getNameFunc: function () {
// var that = this;
// return function () {
// console.log(that.name);// 这个that就是对象了。
// };
// }
// };
// var fn = object.getNameFunc();
// fn();
**********************************
闭包*****
最新推荐文章于 2021-10-18 23:57:34 发布