闭包的常见用法

闭包是什么? 简单来说 就是 一个函数里面, 返回另一个函数。
闭包的作用
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");

我知道的闭包的大概用法就在这里了,如果有什么问题,欢迎指出.

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值