閉包:一個函數被其外部函數以外的變量調用時,就形成了閉包。
function outer(){
function inner(){
console.log("hello baby~")
}
return inner
}
var f = outer()
f()
申明變量f,將outer()賦值給變量。這就是一個簡單的閉包!
for打印出0 - 9
閉包只能取得包含函數中任何變量的最後一個值,這是因爲閉包所保存的是整個變量對象,而不是某個特殊的變量
function test () {
var array = []
for (var i = 0; i < 10; i++) {
array[i] = function () {
return i
}
}
for (var a = 0; a < 10; a++) {
console.log(array[a]())
}
}
test() // 打印出 連續10個10
上例中調用了test(),執行完for (var i = 0; i < 10; i++)時i=10。再接下去執行for (var a = 0; a < 10; a++),調用array[]()向上尋找i,找到了同一作用域的i爲10,同一作用域中同一變量名的變量值肯定是相同的。而我們希望的是打印出0 - 9,下例中我們通過修改 i 的作用域來實現
function test () {
var array = []
for (let i = 0; i < 10; i++) {
array[i] = function () {
return i
}
}
for (var a = 0; a < 10; a++) {
console.log(array[a]())
}
}
test() // 打印出 0 - 9
for (let i = 0; i < 10; i++)在這裏每次循環的塊作用域都被劫持了,並且每次迭代i都被重新聲明。 即在此時,每層迭代會生成一個塊作用域,並且變量i的值被定義爲上次結算的值。另外一種方式
function test () {
var array = []
for (var i = 0; i < 10; i++) {
array[i] = function (a) {
return function(){
return a
}
}(i)
}
for (var a = 0; a < 10; a++) {
console.log(array[a]())
}
}
test() // 打印出 0 - 9
this 對象
var name = 'mm';
var obj = {
name:'ww',
getName:()=>{
return ()=>{
console.log(this.name)
}
}
}
obj.getName()(); //打印出 mm
obj.getName()()實際上是在全局作用域中調用了匿名函數,this指向了window。這裏要理解函數名與函數功能(或者稱函數值)是分割開的,不要認爲函數在哪裏,其內部的this就指向哪裏。匿名函數的執行環境具有全局性,因此其 this 對象通常指向 window。
var name = 'mm';
var obj ={
name:'ww',
getName:()=>{
var that = this;
return ()=>{
console.log(that.name);
}
}
}
obj.getName()();//打印出 ww
閉包優缺點
優點:局部變量不被全局污染
缺點:過度使用閉包,會導致內存佔用過多。