闭包能够理解为定义在一个函数内部的函数,
函数A内部定义了函数B,
函数B有访问函数A内部变量的权力;
闭包是函数和子函数之间的桥梁;
举个例子:javascript
let func = function() { let firstName = 'allen' let innerFunc = function(lastName) { console.log(`hello ${firstName}-${lastName}`) } innerFunc('Liu'); } func();
输出:hello allen-Liu
若是父函数已经退出(返回),那么闭包效用也仍是在的
接着看这个例子:java
let func = function() { let firstName = 'allen' let innerFunc = function(lastName) { console.log(`hello ${firstName}-${lastName}`) } return innerFunc } let innerFunc = func(); innerFunc('Liu'); innerFunc('Zhang');
输出:浏览器
hello allen-Liu hello allen-Zhang
可见,js的执行引擎不但记住了这个内部函数;还记住了这个内部函数所在的环境
就算让这个内部函数引用它的父函数的入参,它也能引用的到!
并且,不但能够引用环境变量,还能够修改环境变量;
再看个例子:闭包
let func = function() { let name = 'allen' let setName = function() { name = 'kivi' } let getName = function() { console.log(name); } return { setName, getName } } let obj = func(); obj.getName(); obj.setName(); obj.getName();
输出结果为:
allen
kivi函数
假设咱们知道一个指向某方法的变量,
咱们能够调用toString方法看这个方法的代码:this
let func = function(x) {console.log(x)}; func.toString();
运行输出:spa
"function(x) {console.log(x)}"
注意输出的是一个字符串,
这是一个很是强悍的功能,你获得这个字符串以后,能够随时eval它,执行方法的逻辑
遗憾的是,你不能信赖toString方法,
由于有时候你拿不到想要的方法体字符串;
举个例子code
let func = (function(x) {console.log(this.x)}).bind({x:123}); func();
输出:123
这是正常的,
由于:bind方法产生了一个新的函数,而且给产生的这个新函数绑定了this,在这里this就是{x:123}
若是调用ip
func.toString();
输出结果就是:开发
"function () { [native code] }"
由于ECMAScript对toString方法并无任何约束,浏览器开发厂商就无所顾忌了 js里的bind方法颇有多是C++实现的,因此你看到了[native code]