問答題
-
函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 (*)
答://函數(shù)聲明 function hello(){ console.log("hello world"); } //函數(shù)表達(dá)式 var hello = function(){ console.log("hello world"); }
兩種方式都能聲明函數(shù),但是函數(shù)聲明的寫法會將函數(shù)前置,可以在全局種任何地方調(diào)用函數(shù);但是表達(dá)式只能前置sayHi變量,如果在表達(dá)式之前調(diào)用函數(shù)則會報(bào)錯(cuò),只能放在表達(dá)式后面進(jìn)行調(diào)用。
-
什么是變量的聲明前置?什么是函數(shù)的聲明前置 (**)
答:- 變量的聲明前置:變量聲明都會被放在代碼的頭部,只提升變量的聲明并不會進(jìn)行賦值。
//全局中定義變量 var a = 1; var b = 2; //實(shí)際是執(zhí)行起來是這樣的 var a; var b; a = 1; b = 2;
//函數(shù)中 function say(){ var a = 1; console.log(a); var b = 2; } //實(shí)際運(yùn)行過程 function say(){ var a; var b; a = 1; console.log(a); b = 2; }
- 函數(shù)聲明前置:函數(shù)的聲明前置和變量聲明一樣,會提升到代碼頭部。但是會提升到變量聲明后面,所以可以在函數(shù)聲明前面調(diào)用函數(shù)。
f(10);//10 此時(shí)該函數(shù)是有效的,且結(jié)果正確 function f(num){ console.log(num); }
相當(dāng)于
function f(num){ cconsole.log(num); } f(10);
-
arguments 是什么 (*)
答:
Arguments是個(gè)類似數(shù)組但不是數(shù)組的對象,說他類似數(shù)組是因?yàn)槠渚邆鋽?shù)組相同的訪問性質(zhì)及方式,能夠由arguments[n]來訪問對應(yīng)的單個(gè)參數(shù)的值,并擁有數(shù)組長度屬性length。還有就是arguments對象存儲的是實(shí)際 傳遞給函數(shù)的參數(shù),而不局限于函數(shù)聲明所定義的參數(shù)列表,而且不能顯式創(chuàng)建 arguments 對象。
Paste_Image.png
arguments對象的長度是由實(shí)參決定的。
-
函數(shù)的重載怎樣實(shí)現(xiàn) (**)
答:
在JavaScript中沒有函數(shù)重載的概念,函數(shù)通過名字確定唯一性,參數(shù)不同也被認(rèn)為是相同的函數(shù),后面的覆蓋前面的。函數(shù)調(diào)用沒必要把所有參數(shù)都傳入,只要你函數(shù)體內(nèi)做好處理就行,但前提是傳的參數(shù)永遠(yuǎn)被當(dāng)做前幾個(gè)。
Paste_Image.png
-
立即執(zhí)行函數(shù)表達(dá)式是什么?有什么作用 (***)
答:(function(){ //第一種 })(); (function(){ //第二種 }());
作用是:立即執(zhí)行函數(shù)可以避免函數(shù)內(nèi)的變量暴露在全局環(huán)境下,避免全局變量的污染。可以令其函數(shù)中聲明的變量繞過JavaScript的變量置頂聲明規(guī)則,還可以避免新的變量被解釋成全局變量或函數(shù)名占用全局變量名的情況,在函數(shù)內(nèi)部內(nèi)部形成了一個(gè)單獨(dú)的作用域,可以封裝一些外部無法讀取的私有變量。
-
什么是函數(shù)的作用域鏈 (****)
答:
在一個(gè)函數(shù)執(zhí)行過程中如果某個(gè)變量在該函數(shù)自己的作用域中沒有,那么它會尋找父級的作用域,直到全局作用域,這樣就形成了一個(gè)作用域鏈。
Paste_Image.png
執(zhí)行ss()時(shí),作用域鏈?zhǔn)牵?ss()->t()->window,所以name是”桶飯"
代碼題
-
以下代碼輸出什么? (難度**)
function getInfo(name, age, sex){ console.log('name:',name); console.log('age:', age); console.log('sex:', sex); console.log(arguments); arguments[0] = 'valley'; console.log('name', name); } getInfo('hunger', 28, '男'); getInfo('hunger', 28); getInfo('男');
輸出結(jié)果:
形參和實(shí)參的數(shù)量可以不一樣,用arguments可以改變實(shí)參的值。
-
寫一個(gè)函數(shù),返回參數(shù)的平方和?如 (難度**)
function sumOfSquares(){ var num; for(var i = 0;i<arguments.length;i++){ num = num+arguments[i]*arguments[i]; } return num; } sumOfSquares(2,3,4); // 29 sumOfSquares(1,3);
-
如下代碼的輸出?為什么 (難度*)
console.log(a); var a = 1; console.log(b); //運(yùn)算過程 var a; console.log(a);//輸出undefined,因?yàn)樽兞刻嵘瑫炎兞縜的聲明提升到console.log(a);之前,當(dāng)console.log(a);執(zhí)行的時(shí)候,變量a還沒有被賦值,所以console.log(a);輸出undefined。 a = 1; console.log(b);//報(bào)錯(cuò),因?yàn)闆]有變量b。
輸出結(jié)果:
-
如下代碼的輸出?為什么 (難度*)
sayName('world'); sayAge(10); function sayName(name){ console.log('hello ', name); } var sayAge = function(age){ console.log(age); }; //運(yùn)算過程 //在執(zhí)行上面代碼的時(shí)候會將函數(shù)的聲明前置,而函數(shù)表達(dá)式只會將變量的聲明前置,函數(shù)不會前置。實(shí)際上述代碼在執(zhí)行的時(shí)候會變成這樣: var sayAge; function sayName(name){ console.log('hello ', name); } sayName('world'); sayAge(10);//sayAge(10);的時(shí)候,sayAge只是個(gè)變量不是函數(shù),所以會報(bào)錯(cuò)。最終會輸出hello world和報(bào)錯(cuò)。 sayAge = function(age){ console.log(age); };
Paste_Image.png -
如下代碼的輸出?為什么 (難度**)
function fn(){} var fn = 3; console.log(fn);//輸出3 //當(dāng)在同一個(gè)作用域內(nèi)定義了名字相同的變量和方法的話,無論其順序如何,變量的賦值會覆蓋方法的賦值。
-
如下代碼的輸出?為什么 (難度***)
function fn(fn2){ console.log(fn2); var fn2 = 3; console.log(fn2); console.log(fn); function fn2(){ console.log('fnnn2'); } } fn(10);
輸出:
//過程
function fn(fn2){
var fn2;//變量聲明前置
function fn2(){
console.log('fnnn2');
}//函數(shù)聲明前置
console.log(fn2);//log fn2()函數(shù)
fn2 = 3;//賦值
console.log(fn2);//log fn2 此時(shí) fn2是3
console.log(fn);//此作用域找不到 fn,向上尋找打印 fn 函數(shù)
}
fn(10);
//函數(shù)執(zhí)行命名有沖突的時(shí)候,函數(shù)執(zhí)行載入順序是變量、函數(shù)、參數(shù)
```
7. 如下代碼的輸出?為什么 (難度***)
```
var fn = 1;
function fn(fn){
console.log(fn);
}
console.log(fn(fn));
```
輸出:

因?yàn)榻o變量聲明進(jìn)行賦值操作后,同名的變量聲明的優(yōu)先級會大于同名函數(shù)聲明,會覆蓋同名的函數(shù)聲明,所以fn現(xiàn)在是一個(gè)變量不是函數(shù),執(zhí)行函數(shù)fn就會報(bào)錯(cuò)。
8. 如下代碼的輸出?為什么 (難度**)
```
//作用域
console.log(j);//輸出undefined,因?yàn)樽兞柯暶髑爸茫琲這時(shí)候還沒有賦值。
console.log(i);//輸出undefined,因?yàn)樽兞柯暶髑爸茫琷這時(shí)候還沒有賦值。
for(var i=0; i<10; i++){
var j = 100;
}
console.log(i);//輸出10,因?yàn)閒or循環(huán)語句結(jié)束循環(huán)時(shí),i的值是10 。
console.log(j);//輸出100,應(yīng)為變量j的值是100。
```
輸出:

9. 如下代碼的輸出?為什么 (難度****)
```
fn();
var i = 10;
var fn = 20;
console.log(i);
function fn(){
console.log(i);
var i = 99;
fn2();
console.log(i);
function fn2(){
i = 100;
}
}
```
```
//過程
var i;
var fn;
function fn() {
var i;
function fn2() {
i = 100;
}
console.log(i);// 輸出undefined,因?yàn)樽兞縤的聲明前置,但還沒有賦值。
i = 99;
fn2();//執(zhí)行函數(shù)fn2,因?yàn)楹瘮?shù)中的變量i沒有加關(guān)鍵字var,所以它是一個(gè)全局變量,它會把100賦值到函數(shù)fn的變量i。這時(shí)i=100
console.log(i);//輸出100,因?yàn)樽兞縤的值為100。
}
fn();
i = 10;
fn = 20;
console.log(i);//輸出10,因?yàn)樽詈笞兞縤的值是10。
```

10. 如下代碼的輸出?為什么 (難度*****)
```
var say = 0;
(function say(n){ //立即執(zhí)行函數(shù),給函數(shù)初始的參數(shù)n=10,當(dāng)滿足n<3時(shí),執(zhí)行say(n-1)。
console.log(n);//輸出10,9,8,7,6,5,4,3,2,因?yàn)楫?dāng)n=2時(shí),函數(shù)return。
if(n<3) return;
say(n-1);
}( 10 ));
console.log(say);//輸出0.因?yàn)榱⒓磮?zhí)行函數(shù)say(n)相當(dāng)于創(chuàng)造了一塊私有的作用域,函數(shù)say(n)內(nèi)部可以訪問外部的變量,而外部環(huán)境不能訪問函數(shù)say(n)內(nèi)部的變量,內(nèi)部定義的變量不會和外部的變量發(fā)生沖突,所以變量say一直等于0。