js進階筆試必會題

來源:互聯網
上載者:User

標籤:++   函數賦值   type   回收   tin   對象   else   傳遞   javascrip   

1. var name = ‘World!‘;
(function () {
if (typeof name === ‘undefined‘) {
var name = ‘Jack‘;
console.log(‘Goodbye ‘ + name);
} else {
console.log(‘Hello ‘ + name);
}
})();

2.var a = 10;
function fn(){
console.log(a);
}

function bar(f){
var a = 20;
f();
}
bar(fn);

3.function sidEffecting(ary) {
ary[0] = ary[2];
}
function bar(a,b,c) {
c = 10
sidEffecting(arguments);
return a + b + c;
}
bar(1,1,1)
結果是 21, 在javascript的變數中 arguments 是個對象,
所以arguments 和局部變數所引用的內容是一樣的。

4.function say666(){
var num = 666;
var sayAlert = function() {
alert(num);
}
num++;
return sayAlert;
}
var sayAlert = say666();
sayAlert()
執行say666()後,say666()閉包內部變數會存在,而閉包內建函式的內部變數不會存在
使得Javascript的記憶體回收機制GC不會收回say666()所佔用的資源。
因為say666()的內建函式的執行需要依賴say666()中的變數。

5.function f1(){
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999
  nAdd();
  result(); // 1000
首先要說的是,閉包是functional language裡面的核心概念。
當出現高階嵌套函數的時候,編譯器會做closure convention閉包變換,核心就是變數不在分配在stack上,而是分配在heap上。這就是為什麼f1已經返回,但是n還能被+1的原因。
樓主給出的這個程式,實際上就是一個高階嵌套函數。
1. 因為在函數裡面有定義的函數,這是嵌套。pascal也是允許嵌套函數。
2. 高階的原因是,函數可以所謂參數傳遞和返回,像我們熟悉的C語言。
但是當高階和嵌套同時出現,就會造成麻煩,所以pascal和C都只能支援其中的一個。
我來分析一下這個程式的執行流。
1. var result=f1(); 返回了一個函數f2, 因此result為f2。這個高階函數特性,參考C語言函數指標。
2. result(); 調用f2,顯然輸出999.
3. nAdd(); 這裡需要注意,這個nAdd實際上在定義的時候是一個lambda,是一個匿名函數,功能是n+=1。定義時將這個函數賦值給nAdd。所以在此時,實際上是調用了n+=1.為什麼能找到n?因為n在堆裡面。
4. result(); 調用f2,顯然輸出1000.
最後一點,n在堆上如何被銷毀,這個工作是垃圾收集器負責。當n不在被任何閉包的env引用的時候,會被回收。
function f1(){
    var n=999;
    function f2(){
      alert(n);
    }
    nAdd=function(){n+=1}
    return f2;
  }
  var result=f1();
  result(); // 999
  nAdd();
  result(); // 1000
var result=f1():f1函數返回了f2函數
把返回的f2函數賦值給result全域變數,(f2的範圍鏈儲存到result全域變數中)
result():調用result(),這就形成閉包:有權訪問另外一個函數範圍中的變數
因為在f2中的範圍引用了f1中的n這個局部變數,當f1執行完畢後,記憶體回收機制發現n變數還在被result中引用所以記憶體回收機制不會把n回收釋放。
以至於n一直儲存在result範圍鏈中。result的範圍鏈正常能訪問f1中的局部變數n,形成閉包。
nAdd():nAdd沒有寫var所以nAdd是全域變數,在調用nAdd()和result()是一樣的都會形成閉包,匿名函數function(){n+=1}的範圍鏈中有n這個局部變數,所以當nAdd=funtion(){n+=1}時,這個匿名函數的範圍鏈儲存到了全域變數nAdd形成閉包,調用nAdd()範圍鏈中找到f1局部變數n=999,n+1=1000。
result():result()就輸出1000
nAdd();重複第三步驟 n+1 = 1001
result();重複第四步驟 輸出n
f1();調用f1時並沒有形成閉包,n永遠都是999,因為每次f1執行結束後n都被記憶體回收機制銷毀了,所以這裡再次調用 var n=999;後面輸出也都是999
為什麼 nAdd 的運算式會影響到 f2 的 n?
因為閉包的原因n一直都沒被銷毀,nAdd()也形成了閉包,並改變了n的值,所以後面再次調用result() n沒被銷毀回收一直被+1,所以會被影響。
最後在調用f1()時沒有閉包,之前n是被銷毀了。所以一直輸出a=999;

6.function fun(n,e) {
console.log(e)
return {
fun:function(m){
return fun(m,n);
}
};
}
var a = fun(0); a.fun(1); a.fun(2); a.fun(3);//undefined,?,?,?
var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?
var c = fun(0).fun(1); c.fun(2); c.fun(3);//undefined,?,?,?
//問:三行a,b,c的輸出分別是什嗎?
//答案:
//a: undefined,0,0,0
//b: undefined,0,1,2
//c: undefined,0,1,1
先看第一個fun函數,屬於標準具名函式宣告,是新建立的函數,他的傳回值是一個對象字面量運算式,屬於一個新的object。
這個新的對象內部包含一個也叫fun的屬性,通過上述介紹可得知,屬於匿名函數運算式,即fun這個屬性中存放的是一個新建立匿名函數運算式。
注意:所有聲明的匿名函數都是一個新函數。
所以第一個fun函數與第二個fun函數不相同,均為新建立的函數。

js進階筆試必會題

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.