JS_闭包其实很简单
2019-12-08 本文已影响0人
learninginto
JS_闭包其实很简单
闭包.jpg闭包其实就是一个函数,执行以后,接受里面返回的函数,然后保存到一个全局变量中。
要理解闭包,首先必须理解Javascript特殊的变量作用域。
变量的作用域无非就是两种:全局变量和局部变量。Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。
- 全局变量
var a = 6;//a是全局变量
function fun1(){
console.log(a)
}
fun1();
- 局部变量
注意:如果b = 6; 前面不写var,b就被升级为全局变量了
var a = 6
function fun1(){
var b = 6;
}
fun1();
console.log(b);//b is not defined
- 如何读取局部变量的值?
出于种种原因,我们有时候需要得到函数内的局部变量值。
但是,正常情况下,这是办不到的,只有通过变通方法才能实现。
function fun1(){
var a = 6;
function fun2(){
return a;
}
return fun2;
}
console.log(fun1()());
案例中fun1是一个函数,里面套叠了一个fun2的函数,
因为fun2和a从属一个作用域下,因此可以返回a的值。
最后执行的把fun2这个函数通过fun1返回出去。
因此fun1()执行以后就是fun2,而fun2要执行就需要给他再加一个(),因此就变成了fun1()();你也可以通过赋值的方法将它拆解开,例如:
var fun = fun1();
var a1 = fun();
console.log(a1);
- 使用闭包很重要的原因:
让内部的函数有权访问外部的局部变量,以防止变量的重名污染 。
var b = 3;
function fn() {
var sum = 3;//私有变量,相当于面向对象中的私有private static
//定义的函数fun1,里面有一个sum,前面我们说过return是可以返回任何值包括函数
return function () {
sum++;
console.log(sum);
}
}
var fn1 = fn();
fn1();//4
fn1();//5
fn1 = null;
//直到fn1被赋值为null的时候,fn当中的匿名函数引用才被切断,这时候也把这个sum清理掉了。
由此可见,闭包有如下特点
- 闭包的特点
- 函数嵌套函数
- 函数内部可以引用外部的参数和变量
- 参数和变量不会被垃圾回收机制回收
- 闭包的优点
- 希望一个变量长期驻扎在内存中
- 避免全局变量的污染
- 私有成员的存在
- 利用闭包,返回一个对象或函数
Utils.js
var Utils = function(){
var a = 1;
return{
a:2,
ce:function(){
a++;
this.a++;
console.log(a,this.a);
}
}
}
var obj = (function(){
function fun1(){
}
function fun2(){
}
return {fn1:fun1, fn2:fun2};
})
其他页面调用Utils.js
Utils.ce(); // 打印2,3
obj.fn1();
obj.fn2();
- 利用闭包实现bind()
Function.prototype.bind1 = function(obj){//这里的函数参数obj,也是局部变量,因此在下面的return语句中,可以访问到
var self = this;
return function(){
return self.apply(obj, Array.from(arguments));
}
}
function fn1(a, b){
this.a = a;
this.b = b;
return this;
}
var fn = fn1.bind1({});
var obj = fn(3, 5);
console.log(obj);
- 举一反三,应用案例
Function.prototype.bind1 = function(obj){
var self = this;
return function(){
return self.apply(obj, Array.from(arguments));
}
}
var obj = {
num:1,
init:function(){
document.addEventListener("click"), this.clickHandler.bind1(this);
},
clickHandler:function(){
this.num++;
console.log(this.num);
}
}
obj.init();