在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/HTML/ 為什么這道題目答案不全是4

為什么這道題目答案不全是4

var a=2;
var func=(function(){
    var a=3;
    return function(){
       a++;
       alert(a);
    }
})();

func();
func();


經(jīng)運(yùn)行分別是4,5 為什么不全是4呢
回答
編輯回答
嫑吢丕

作用域鏈!

你的代碼可以拆解為:

var a = 1;

var fn = function(){
    var a=3;
    return function(){
       a++;
       alert(a);
    }
}
// 自執(zhí)行過程
var func = fn();

func(); // => 4
func(); // => 5

鏈1:global -> a
鏈2:global -> func -> a

所以 return function 執(zhí)行時,會按這個規(guī)則去找變量a,找到的即是鏈2的!

2017年9月23日 16:08
編輯回答
情未了

好好研究一下閉包
教程

2018年4月29日 10:23
編輯回答
怣痛

自執(zhí)行函數(shù)自己有一個作用域,return出來的那個函數(shù)里面操作的a是自執(zhí)行函數(shù)環(huán)境下的a。且返回的這個函數(shù)中對a的引用在程序結(jié)束前沒有釋放。所以第一次執(zhí)行func時修改了a,第二次在執(zhí)行的時候a還會疊加,并沒有重新創(chuàng)建這個環(huán)境。

相當(dāng)于

var a = 1;
function plus(){
    a++;
}
plus();
plus(); 
console.log(a) // 3
2018年1月15日 03:00
編輯回答
青檸

返回函數(shù)里的a是func里的啊 修改的也是func里的a

2017年1月5日 19:17
編輯回答
萌小萌

這個題是典型的考查JS的代碼執(zhí)行原理,其執(zhí)行過程解析如下:
1、當(dāng)JS引擎遇到上面的這段代碼時,會創(chuàng)建一個全局執(zhí)行上下文(一個執(zhí)行上下文的生命周期包含兩個階段,即創(chuàng)建階段和執(zhí)行階段);

2、創(chuàng)建階段,JS引擎會做如下工作:
a,創(chuàng)建變量對象(Variable Object -> VO),注:全局執(zhí)行上下文和函數(shù)執(zhí)行上下文有一點(diǎn)區(qū)別的,全局是沒有arguments的相關(guān)操作

 a-1、查找function函數(shù)聲明,在VO上添加一個屬性,屬性名為函數(shù)名,屬性值為函數(shù)在內(nèi)存中的引用,遇    
      同名覆蓋
 a-2、查找var變量聲明,在VO上添加一個屬性,屬性名是變量名,屬性值為undefined,遇同名跳過
 這一步完成后的結(jié)果如下:
  VO = {
     a:undefined,
     func:undefined 
  } 
 

b,建立作用域鏈

 作用域鏈其實(shí)就是一個數(shù)組,在數(shù)組的頂端存放的永遠(yuǎn)是當(dāng)前執(zhí)行上下文的VO對象,在全局執(zhí)行上下文中,作
 用域鏈中只有一個全局的VO,即 [Global_Context.VO],此時JS引擎還做做一件事情,給當(dāng)前執(zhí)行上下文中函數(shù)添加個內(nèi)部屬性[[scope]](我們不能使用,僅供JS引擎使用)
 比如:fn.[[scope]] = [Global_Context.VO]

c,確定this指向

 這里this->window

一個執(zhí)行上下文創(chuàng)建完成后壓入棧

3、執(zhí)行階段,該階段主要完成變量賦值、函數(shù)調(diào)用等等操作,此時 VO(用戶不可操作) -> AO(用戶可操作)(注:VO/AO是同一個對象,不同階段的不同叫法)
首先遇到 a = 2;JS引擎會去當(dāng)前執(zhí)行上下文的作用域鏈中查找(查找的過程是從第一個AO對象開始,依次查找,如果找到,則返回;否則繼續(xù)查找,直到全局的AO,如果還找不到,則報錯。)
這一步完成后的結(jié)果是如下:
AO={

  a:2,
  /* 
  注:由于func表達(dá)式后面是一個自執(zhí)行匿名函數(shù),所以func的值最終是自執(zhí)行匿名函數(shù)執(zhí)行后的結(jié)果,
  這個自執(zhí)行匿名函數(shù)執(zhí)行時,也會創(chuàng)建對應(yīng)的執(zhí)行上下文,和上面的過程一樣的,有自己的AO、作用域鏈
  這里的作用域鏈?zhǔn)怯僧?dāng)前執(zhí)行上下文的VO和函數(shù)的內(nèi)部屬性[[scope]]組合而成,則function(){ a++;alert(a); }此函數(shù)
  也有內(nèi)部屬性[[scope]]指向父級執(zhí)行上下文的作用域鏈,由于function(){ a++;alert(a); }被外部變量引用著,而該函數(shù)
  的[[scope]]有指向自執(zhí)行匿名函數(shù)的作用域鏈,所以當(dāng)自執(zhí)行匿名函數(shù)執(zhí)行完畢后,執(zhí)行上下文彈出棧,但不會被銷毀,而是
  又保存到內(nèi)存中其他位置。
  */
  func:function(){
          a++;
          alert(a);
       }

}
作用域鏈 [AO,Global_Context.VO]
4、第一次執(zhí)行func()時,首先會在func的執(zhí)行上下文的AO中查找a,沒有找到,就繼續(xù)到父級執(zhí)行上下文的AO中找,找到a是3,然后+1,得4
5、第二次執(zhí)行func時,同樣的執(zhí)行過程,首先會在func的執(zhí)行上下文的AO中查找a,沒有找到,就繼續(xù)到父級執(zhí)行上下文的AO中找,找到a是4,然后+1,得5

上述執(zhí)行過程涵蓋了變量提升、作用域、作用域鏈、閉包(插一個題外話:為什么閉包可以外部訪問內(nèi)部變量,很多人都知道可以訪問,但是為什么能訪問? 上面已經(jīng)給出解釋)

以上是本人對JS的底層執(zhí)行原理的大體認(rèn)識,尚有細(xì)枝末節(jié)未涉及,不足之處難免,僅供參閱。

2017年7月20日 12:09
編輯回答
來守候

閉包
var xx = ()();

2017年1月8日 14:50