一、作用域[[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課程" ,一個值得推薦的"渡一教育"。