一、作用域[[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();//33 、实现属性私有化(第二块代码为圣杯模式,后续继承会涉及),别人访问不到,自己可以操作。
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课程" ,一个值得推荐的"渡一教育"。