1.函數(shù)聲明和函數(shù)表達式有什么區(qū)別 ?
1.函數(shù)聲明必須有標識符,也就是常說的函數(shù)名;函數(shù)表達式可以省略函數(shù)名。
2.函數(shù)聲明會提前。
3.ECMAScript規(guī)范中表示,函數(shù)聲明語句可以出現(xiàn)在全局代碼中,或者內嵌在其他函數(shù)中,但是不能出現(xiàn)在循環(huán)、條件判、或者try/finally以及with語句中。
注:其實兩者最重要的區(qū)別就是函數(shù)聲明前置的問題,一定要注意這一點。
2.什么是變量的聲明前置?什么是函數(shù)的聲明前置?
當我們寫出:
var a = 1;
function sum(){
var sum = 0;
for(var i=0;i<arguments.length;i++){
sum = sum + arguments[i];
}
return sum;
}```
實際上最終會被解析為:
var a;
function sum(){
var sum = 0;
for(var i=0;i<arguments.length;i++){
sum = sum + arguments[i];
}
return sum;
}
a = 1```
變量的聲明和函數(shù)的聲明都會被提到最前,順序是先變量聲明,后函數(shù)聲明,后面的聲明會覆蓋前面的聲明。
3.arguments 是什么?
arguments 是JavaScript里的一個內置對象,所有函數(shù)都有屬于自己的一個arguments對象,它包括了函所要調用的參數(shù),即使沒有明確寫出來,也會默認有arguments.
例:
function getInfo(name,age,sex){
console.log('name:',name);
console.log('age:',age);
console.log('sex:',sex);
console.log(arguments);
arguments[0] = 'xiaoming';
console.log('name:',name);
}
getInfo('hunger',18,'男');
}```
name,age,sex分別對應 0,1,2的位置,我們可以通過
``argumengts[0[]= 'xiaoming';``來使所有處于 0 位置的變量為 ‘xiaoming'
##4.函數(shù)的重載怎樣實現(xiàn)?
ECMAscript函數(shù)不能像傳統(tǒng)意義上那樣實現(xiàn)重載,一旦對函數(shù)聲明了兩次,函數(shù)會默認使后者覆蓋前者。我們可以使用其他方式來實現(xiàn)重載效果:
function sum() {
var sum = 0;
for (var !=0;i<arguments.length;i++) {
sum = sum + arguments[i];
}
return sum;
}
console.log(sum(1,2,10));
最后可得:
13```
5.立即執(zhí)行函數(shù)表達式是什么?有什么作用?
function say(){
console.log("hello");
}
say();```
上面的函數(shù)必須通過``say()``調用后才可以執(zhí)行,``function say(){}``只是聲明這個函數(shù),并沒有執(zhí)行函數(shù)。
我們可以通過對整個函數(shù)加小括號來使函數(shù)聲明變成一個表達式,從而立即執(zhí)行:
(function say(){
console.log("hello");
})();
或
(function say(){
console.log("hello");
}());
雖然是一個表達式,但是是包裹在函數(shù)中的,此時若在此函數(shù)內加上``var i = 100;``也只會在此表達式內生效,對其他表達式不影響。其作用就是包裹一段代碼,讓這段代碼擁有自己的作用域,要注意的是,這是一個表達式,所以不會前置,而且立即執(zhí)行后,在其他地方也無法調用。
##6.什么是函數(shù)的作用域鏈
首先要明確什么是**作用域**:
作用域就是變量和函數(shù)的可訪問范圍,控制著變量和函數(shù)的可見性與生命周期,在JavaScript中變量的作用域有全局作用域和局部作用域。
**作用域鏈:**
當代碼在一個環(huán)境中執(zhí)行時,會創(chuàng)建變量對象的一個作用域鏈(scope chain,不簡稱sc)來保證對執(zhí)行環(huán)境**有權**訪問的變量和函數(shù)的**有序**訪問。作用域第一個對象始終是當前執(zhí)行代碼所在環(huán)境的變量對象。
function a(x,y){
var b=x+y; return b;
}```
在函數(shù)a創(chuàng)建的時候它的作用域鏈填入全局對象,全局對象中有所有全局變量.
如果執(zhí)行環(huán)境是函數(shù),那么將其活動對象(activation object, AO)作為作用域鏈第一個對象,第二個對象是包含環(huán)境,依次向其父級作用域尋找變量。
function a(x,y){
var b=x+y; return b;
}
var tatal=a(5,10);```
此時 ``var tatal=a(5,10);``的作用域如下:

在函數(shù)運行過程中標識符的解析是沿著作用域鏈一級一級搜索的過程,從第一個對象開始,逐級向后回溯,直到找到同名標識符為止,找到后不再繼續(xù)遍歷,找不到就報錯。
***
##代碼:
##1.以下代碼輸出什么?
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('男');

##2.寫一個函數(shù),返回參數(shù)的平方和
```function sumOfSquares(){
var sum = 0;
for(i=0;i<arguments.length;i++){
sum = sum + arguments[i]*arguments[i];
}
console.log(sum);
return sum;
}
sumOfSquares(2,3,4);
sumOfSquares(1,3);```.
##3.如下代碼的輸出?為什么
console.log(a);
var a = 1;
console.log(b);```
變量提升:
var a;
console.log(a);//undefined(因為聲明了 a 但沒有賦值)
a = 1;
console.log(b);//b is not defined(沒有聲明 b)
4.如下代碼的輸出,為什么
sayName('world');
sayAge(10);
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};```
變量提升:
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age); //這是一個函數(shù)表達式,不會變量前置。
}
sayName('world');
sayAge(10); ```
所以最后輸出:
hello,world
10
5.如下代碼的輸出?為什么
function fn(){
}
var fn = 3;
console.log(fn);
變量提升:
var fn;
function fn(){
}
fn = 3;
console.log(fn);//3
輸出: 3
6.如下代碼的輸出?為什么
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(){//函數(shù)聲明
console.log('fnnn2');
}
console.log(fn2);
fn2 = 3;
console.log(fn2);
console.log(fn);
}
fn(10);```
輸出結果:
7.如下代碼的輸出?為什么
var fn = 1;
function fn(fn){
console.log(fn);
}
console.log(fn(fn));
變量提升:
var fn;
function fn(fn){
console.log(fn);
}
fn = 1;
console.log(fn(fn));```
經過變量提升后,fn已經不是一個函數(shù)了,所以輸出``fn is not a function``
##8.如下代碼的輸出?為什么
``` //作用域
console.log(j);
console.log(i);
for(var i=0; i<10; i++){
var j = 100;
}
console.log(i);
console.log(j);```
變量提升:
var j;
var i;
console.log(j);//undefined
console.log(i);//undefined
for(i = 0; i<10;i++){
j =100;
}
console.log(i);//10
console.log(j);//100
for是表達式,不是函數(shù),沒有自己的單獨作用域,所以``var j = 100;``和``var i =0;``會被前置。最后得到:
undefined
undefined
10
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
i =99;
fn2( );
console.log(i);//100
}
fn();
i = 10;
fn = 20;
console.log(i);//10
最后得出:
undefined
100
10
10.如下代碼的輸出?為什么
var say = 0;
(function say(n){
console.log(n);//10
if(n<3) return;
say(n-1);//9,8,7,6,5,4,3,2
}( 10 ));
console.log(say);//0
此段代碼中的函數(shù)為立即執(zhí)行函數(shù),可以看作是一個表達式,所以不會被前置。若n>3,立刻return輸出say