首页 > 其他 > 详细

JavsScript 闭包 (Closure)

时间:2020-10-30 18:58:04      阅读:28      评论:0      收藏:0      [点我收藏+]

欢迎各位大佬指导!!!

前言:

? 要理解闭包首先需要了解javascript的变量作用域,JavaScript的变量作用域分为两种:

  1. 全局作用域
  2. 局部作用域

全局变量的作用域是全局性的,在整个javaScript程序中都在,而在函数内声明的变量作用域,只在函数内起作用。

eg: 在JavaScript中函数内部可以直接访问全局作用域的变量

var a = 123; // 定义全局变量 a
function fn(){
	alert(a); // 在函数内部访问全局变量a
}
fn(); // 调用函数 fn() 弹框结果 123

但是函数内的局部变量,在外面不能访问到。

function fn(){
	var a = 123; // 定义局部变量
}
alert(a); // a 未定义

注意:在函数内部定义局部变量时,如果没有用 var 声明,那这个变量就是全局变量。即外部就可以访问到这个变量。

如果想要获取函数内定义的局部变量,那么用闭包就可以获取到函数内部的局部变量。

闭包的概念闭包是指有权访问一个函数作用域中的变量的函数。

? 那么闭包的作用就很明显了:

  1. 可以在函数外部访问到函数内部的局部变量。
  2. 让这些变量始终保存在内存中,不会随着函数的结束而自动销毁。

是否使用闭包要考虑这两点:隔离和数据保存。如果需要隔离数据并形成命名空间,可以使用匿名自执行函数 ;如果还需要在隔离状态下保存数据,保存之后后面还可以继续使用,那就可以使用闭包,如果及不需要隔离和数据保存,那就使用普通函数,在函数调用完后,数据就释放了。

来看下面的两端代码

代码一:

var name ="The Window";
var object = {
	name : "My Object",
	getNameFunc:function(){
		return funcion(){
			return this.name;
		}	
	}
};

alert(object.getNameFunc() ());

运行结果: The Window

代码二:

var name = "The Window";
var object = {
	name: "My Object",
	getNameFunc: function(){
		var that = this;
		return function(){
			return that.name;
		}
	}
};

alert(object.getNameFunc() ());

运行结果: My Object

思考一下,这是为何??

我们来分析一下,首先来看代码一:

// 首先在Javascript中 定义全局变量、全局对象、全局函数 都自动属于window对象的成员。也就是说它们都是window对象的属性,可以用window.出来。
var name = "The Window"; // 这是定义了一个name 的全局变量
var object = {   // 这是定义了一个object 的全局对象
	name: "My Obejct", // 局部变量 name
	getNameFunc: function(){ // 局部函数 getNameFunc 返回的是一个匿名函数
		return function(){
            // 此处的this 指的是window对象,为什么这样说呢,是因为哪个对象调用this所在的函数,this指的就是哪个对象。
             // alert(object.getNameFunc() ()) 首先调用了 object.getNameFunc的函数返回了一个匿名函数function(){return this.name} 此时这个匿名函数是全局函属于window对象,所以在调用匿名函数的时候,return this.name 的结果是 The Window
			return this.name; 									 
		}
	}
};

alert(object.getNameFunc() ());

我们再来分析一下 代码二:

var name = "The Window"; // 同样定义全局的name变量
var object = {  // 定义全局的object全局对象
    name: "My Object",  // 定义局部变量
    getNameFunc: function(){  // 定义局部函数 getNameFunc()
        var that = this; // 此时当alert(object.getNameFunc()()) 调用时object调用getNameFunc函数,哪个对象调用this,this指的就是哪个对象,显然this指向的是object对象。然后 var that = this 将 object对象赋值给 that 然后返回匿名函数此时匿名函数中引用了that变量,所有当再次的调用匿名函数是return that.name 就等同于 return object.name 即输入结果为 My Object
        return function(){
            return that.name;
        }
    }
    
};

alert(object.getNameFunc() ());

OK,我们来看一道经典题

function fun(n,o){
	console.log(o);
	return {
		fun:function(m){
			return fun(m,n);
		}
	}
}
var a = fun(0);a.fun(1);a.fun(2);a.fun(3); //输入结果: undefined 0 0 0
var b = fun(0).fun(1).fun(2).fun(3); //输入结果: undefined 0 1 2

思考一下,OK ,我们来分析一下产生结果的原因。

var a = fun(0);a.fun(1);a.fun(2);a.fun(3); // 我们来拆分一下这段代码

var a= fun(0); 
a.fun(1);
a.fun(2);
a.fun(3);
// 当执行第一行代码时,调用最外面的fun(n,o)函数,传入0,所以console.log(o)的结果为undefined,因为只传了一个参数。然后返回一个对象
// {fun:function(m){return fun(m,n)}}
// 将这个对象赋值给了变量a 即 a = {fun:function(m){return fun(m,n)}}

// 执行第二行代码时,调用fun:function(m)函数,此时m为1;因为a是第一次的对象传入了0。 所以此时的 n 为0;即 return fun(1,0) 再次调用最外面的fun(n,o)函数,打印o为0;

// 当执行第三行代码时,还是调用fun:function(m)函数,此时m为2;因为a是第一次的对象传入了0。 所以此时的 n 为0;即 return fun(2,0) 再次调用最外面的fun(n,o)函数,打印o为0;

// 当执行第四代码时,同上;打印o为0;

Ok ,第一个分析完毕,我们再来分析一下第二个输入出结果。

var b = fun(0).fun(1).fun(2).fun(3); // 同样我们把这行代码拆分一下

var b = fun(0)
    .fun(1)
    .fun(2)
    .fun(3);

// 当执行第一行代码时,依然是调用最外面的fun(n,o)函数,并且传入n=0; 即第一次打印的o为undefined,然后返回一个对象
// {fun:function(m){return fun(m,n)}}

// 当执行第二行代码时,调用fun:function(m)函数,因 .fun(1) 此时m为1;此时 n 为上一次的值 0 ,即 return fun(1,0),再次调用最外面的函数 fun(n,o)
// 此时n 为 1; 打印 o 为 0 ,然后 return 返回。

// 当执行第三行代码时,调用fun:function(m)函数,因 .fun(2) 此时m为2;此时 n 为第二行执行后的值, n=1; 即 return fun(2,1) ,再次调用最外面的函数 fun(n,o) 此时 n 为 2 , o 为 1 ,即 打印 1,然后返回。

// 当执行第四行代码时,调用fun:function(m)函数,因 .fun(3) 此时m为3;此时 n 为第三行执行后的值, n=2; 即 return fun(3,2) ,再次调用最外面的函数fun(n,o) 此时 n 为 3 , o 为 2,即 打印 2, 然后返回。

未完待续。。。。。

JavsScript 闭包 (Closure)

原文:https://www.cnblogs.com/1204it-ly/p/13903189.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!