一、作用域[[scope]]:
存储了执行期上下文的集合(作用域链)
参照下图代码:
a函数被定义时:a.[[scope]]--> 0:GO{}
a函数执行时:a.[[scope]]--> 0:aAO{}
1:GO{}
a函数执行时,b函数被定义:b.[[scope]]-->0:aAO{}
1:GO{}
b函数毫不客气地带上了老爹a函数的劳动成果。
b函数执行时:b.[[scope]]-->0:bAO{}
1:aAO{}
2:GO{}
在哪个函数里查找变量,就从哪个函数的作用域链的顶端依次向下查找
b函数执行结束,摧毁自己的执行期上下文,回归到被定义时的状态,等待下一次执行
a函数执行结束,摧毁自己的执行期上下文(同时摧毁了整个b函数),回归到被定义时的状态,等待下一次执行
二、闭包:还是举栗说明
当a函数将其内部的b函数return,并赋给外部变量demo时,
此时的b函数保存了a函数执行时的作用域链,不会被释放。形成闭包。
如此一来,若过多的作用域链不被释放,占用大量内存,造成内存泄露。
闭包的应用:
1、用做缓存(存储结构)
function eater(){
var food = '';
var obj = {
eat: function() {
console.log('I am eating ' + food);
food = '';
},
push: function(myFood){
food = myFood;
}
}
return obj;
}
var eater1 = eater();
eater1.push('banana');
eater1.eat();
2、实现公有变量,函数累加器
function add(){
var count = 0;
function demo(){
count++;
console.log(count);
}
return demo;
}
var counter = add();
counter();//1
counter();//2
counter();//3
3 、实现属性私有化(第二块代码为圣杯模式,后续继承会涉及),别人访问不到,自己可以操作。
function Person(name,club){
var prepareClub = 'Laker';
this.name = name;
this.club = club;
this.changeClub = function(){
this.club = prepareClub;
}
this.changePrepareClub = function(target){
prepareClub = target;
}
this.sayPrepareClub = function(){
console.log(prepareClub);
}
}
var person = new Person('Jame','Heat');
下图代码为圣杯模式,后续继承模式会详细说明。
var inherit = (function(){
var F = function(){};
return function(Target,Origin){
F.prototype = Orgin.prototype;
Target.prototype = new F();
Target.prototype.constructor = Target;
Target.prototype.uber = Origin.prototype;
}
}());
4、模块化开发,防止污染全局变量
var name = 'bcd';
var initJack = (function(){
var name = 'abc';
function callName(){
console.log(name);
}
return function(){
callName();
}
}());
initJack();
三、立即执行函数:有些函数只需要执行一次,初始化功能,执行完立即释放。
var num = (function(a,b){
return a + b;
}(3,5));
console.log(num);//8
立即执行函数拓展:
只有表达式才能被执行符号执行!!!如下列代码,+、-将函数test转换为表达式
能被执行符号执行的函数表达式,自动放弃函数名称。
+function test(){
console.log('a');
}();
-function test(){
console.log('b');
}();
经典鄙视题 :以下代码如何执行?
function demo(a,b,c,d){
return a + b + c + d;
}(1,2,3,4)
四、闭包的防范:如下两段代码,感受一下。
function test(){
var arr = [];
for(var i = 0; i < 10; i++){
arr[i] = function(){
console.log(i);//打印10个10
}
}
return arr;
}
var myArr = test();
for(var j = 0; j < 10; j++){
myArr[j]();
}
function test(){
var arr = [];
for(var i = 0; i < 10; i++){
(function(j){
arr[j] = function(){
console.log(j);//0123456789
}
}(i));
}
return arr;
}
var myArr = test();
for(var j = 0; j < 10; j++){
myArr[j]();
}
以上内容属二哥原创,整理自 "渡一教育Javascript课程" ,一个值得推荐的"渡一教育"。