JavaScript 匿名函數(shù)及閉包

2018-08-12 12:00 更新

采用自執(zhí)行的匿名函數(shù)解決for循環(huán)使用閉包的問(wèn)題


這段代碼輸出的是10個(gè)10而不是期望的0到9,因?yàn)殚]包內(nèi)是對(duì)i的引用,然后函數(shù)執(zhí)行時(shí)i已經(jīng)變成了10

function f1(){
for(var i = 0; i < 10; i++) {
setTimeout(function() {
alert(i); 
}, 1000);
}
}
f1();

解決以上的問(wèn)題可以采用自執(zhí)行的匿名函數(shù)

function f2(){
for(var i = 0; i < 10; i++) {
(function(e) {
setTimeout(function() {
alert(e); 
}, 1000);
})(i);
}
}
f2();
這里的匿名函數(shù)將i作為參數(shù),這里的e會(huì)有i的一個(gè)拷貝,而引用時(shí)是對(duì)e的引用,這就避免了上述的問(wèn)題



一 .關(guān)于閉包


理解閉包 需要的知識(shí)
1.變量的作用域
例1:

var n =99; //建立函數(shù)外的全局變量
function readA(){
  alert(n); //讀取全局變量
}


readA(); //執(zhí)行此函數(shù)
例2:

function readB(){
  var c = 9;
  function readC(){
    console.log(c); //ok c可見(jiàn)
  }
  return readC;
}
alert(c); //error c is not defined.


note:  函數(shù)內(nèi)部聲明變量c時(shí),一定要加上 var,否則 c會(huì)成為一個(gè)全局變量
所以函數(shù)內(nèi)可見(jiàn)全局變量,函數(shù)內(nèi)的局部變量卻對(duì)外不可見(jiàn)
js的作用域是鏈?zhǔn)降?父對(duì)象里的變量總對(duì)子對(duì)象可見(jiàn),子對(duì)象的對(duì)象卻對(duì)父對(duì)象不可見(jiàn)
當(dāng)我們要獲取函數(shù)內(nèi)的內(nèi)部變量
于是有了例3:

function readB(){
  var c = 9;
  function readC(){
    console.log(c);
  }
  return readC();
}
readB();
閉包很類似基于此做了一個(gè)變式

function readB(){
  var c = 9;
  function readC(){
    console.log(c);
  }
  return readC;
}
var res = readB();
res();
note:


1.慎用閉包,注意內(nèi)存占用,因?yàn)樗鼤?huì)保存父函數(shù)的狀態(tài)
2.不要隨便改變父函數(shù)內(nèi)部變量的值
理解閉包
   note: this 指包含它的函數(shù)被執(zhí)行時(shí)所屬的對(duì)象
例1:

var name = "The Window";
 
var object = {
  name : "My Object",
 
  getNameFunc : function(){  //此時(shí)this (這個(gè)執(zhí)行函數(shù))是屬于object對(duì)象的,是object對(duì)象下的一個(gè)屬性的值
    return function(){   //此時(shí)this (這個(gè)執(zhí)行函數(shù))是一個(gè)匿名函數(shù),從根對(duì)象window生成,是屬于window
      return this.name;
    };
  }
};


console.log(object.getNameFunc()()); //the window

var name = "The Window";
 
var object = {
  name : "My Object",
 
  getNameFunc : function(){
    var that = this;
    return function(){
      return that.name;
    };
 
  }
};
console.log(object.getNameFunc()());  //My Object


二 .匿名函數(shù)


直接定義一個(gè)匿名函數(shù) 然后調(diào)用這個(gè)匿名函數(shù),這種形式在jquery插件的定義時(shí)很常見(jiàn)
1.通過(guò)函數(shù)字母量的方式. 先聲明一個(gè)匿名函數(shù),然后執(zhí)行它

( function(){
  console.log('excute self');
}) ();


2.通過(guò)優(yōu)先表達(dá)式的方式 , 由于Javascript執(zhí)行表達(dá)式是從圓括號(hào)里面到外面,所以可以用圓括號(hào)強(qiáng)制執(zhí)行聲明的函數(shù)

(
  function () {
    alert(2);
  }
  ()
);


3.void操作符 用void操作符去執(zhí)行一個(gè)沒(méi)有用圓括號(hào)包圍的一個(gè)單獨(dú)操作數(shù)
?
1
void function(){ console.log('void') } ();


三 .關(guān)于prototype


原型 prototype
理解js中的protitype首先需要明白js的面向?qū)ο笤O(shè)計(jì)

function People(name){
  this.name = name;
 
  console.log(this); //Window 或者 object { name: 'xxx' }
  this.introduce = function(){  //實(shí)例對(duì)象方法
    console.log(this.name);
  }
}
new People('leon').introduce();


//這里有一個(gè)非常有趣的現(xiàn)象,結(jié)合前面的來(lái)看的話,
//首先f(wàn)unction people里的this指向的默認(rèn)是Window對(duì)象
//當(dāng) 調(diào)用 People();時(shí) this 輸出為 Window對(duì)象
//但一旦調(diào)用new People('xx')時(shí), this 輸出為 {name:'xx'}
//其實(shí)也很好理解,一旦new ,便新建了一個(gè)對(duì)象
實(shí)例對(duì)象方法只能這樣 new People('leon').introduce(); 調(diào)用 因?yàn)樗褂们氨仨毘跏蓟?br />類的對(duì)象的靜態(tài)方法

var People = {}; //等于一個(gè)對(duì)象 {} 或者 function 數(shù)組都可以 此時(shí)People需要是引用類型
People.sayhi = function(to_who){
  console.log('hi '+ to_who);
}
People.sayhi('lee'); //調(diào)用時(shí)這樣調(diào)用


原型方法

var People = function(){};       // People 必須為一個(gè) function(){} 即為一個(gè)類,不能是對(duì)象或值類型或其他引用類型
People.prototype.meet = function(meet_who) {
  console.log('I am '+this.name + ',going to meet ' + meet_who);
};
new People('lee').meet('xx');
原型方法只能由該類的對(duì)象 調(diào)用
 A.prototype = new B();
原型看起來(lái)很像繼承,但其實(shí)不是,它更像clone更準(zhǔn)確
如果出現(xiàn)了父類和子類出現(xiàn)了重名的屬性,采取就近原則,如果找不到一級(jí)一級(jí)向上找,如果要指定調(diào)用上級(jí)的屬性,使用call方法

extendClass.prototype = new baseClass();
var instance = new extendClass();
var baseinstance = new baseClass();
baseinstance.showMsg.call(instance);
obj1.func.call(obj);



以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)