函數(shù)聲明和函數(shù)表達式有什么區(qū)別伟墙?
函數(shù)聲明:function fn(){}
函數(shù)表達式:var fn = function(){};
- 都可以定義一個函數(shù)蟹略。
- 函數(shù)聲明會產生函數(shù)的聲明前置,因此可以在函數(shù)聲明之前就調用函數(shù)凿菩。函數(shù)表達式只會產生變量的聲明前置凉唐,因此在函數(shù)表達式之前調用會報錯极颓。
- 函數(shù)聲明語句不能出現(xiàn)在if語句,while循環(huán)和其他任何語句中购桑,表達式則可以畅铭。
什么是變量的聲明前置?什么是函數(shù)的聲明前置勃蜘?
- 變量的聲明前置硕噩,JavaScript代碼在解析時,會首先獲取所有被聲明的變量(只有變量名缭贡,不包含其值)炉擅,使所有變量的聲明語句會提升到代碼的頭部辉懒。
- 函數(shù)的聲明前置,JavaScript代碼在解析時谍失,先獲取所有被聲明的函數(shù)眶俩,使函數(shù)在執(zhí)行任何代碼之前都可以訪問。
arguments是什么快鱼?
- arguments 是一個類數(shù)組對象颠印,相當于傳入的所有函數(shù)的集合,可以使用方括號語法訪問它的每一個元素抹竹。
函數(shù)的重載怎樣實現(xiàn)线罕?
在JavaScript中沒有函數(shù)重載的概念,函數(shù)通過名字確定唯一性窃判,參數(shù)不同也被認為是相同的函數(shù)闻坚,后面的覆蓋前面的,但可以通過自身屬性模擬函數(shù)的重載兢孝。
function printPeopleInfo(name, age, sex){
if(name){
console.log(name);
}
if(age){
console.log(age);
}
if(sex){
console.log(sex);
}
}
printPeopleInfo('Byron', 26);
printPeopleInfo('Byron', 26, 'male');
立即執(zhí)行函數(shù)表達式是什么?有什么作用 ?
立即執(zhí)行函數(shù)表達式結構:
(function() {code} (可傳入參數(shù)) );
(function () {code})(可傳入參數(shù));
```
* 不必為函數(shù)命名仅偎,避免了污染全局變量跨蟹;
* 立即執(zhí)行函數(shù)執(zhí)行完后就會銷毀,不會對作用域存在影響橘沥;
* 在函數(shù)內部形成一個單獨的作用域窗轩,可以封裝一些外部無法讀取的私有變量;
## 什么是函數(shù)的作用域鏈座咆?
作用域:指對變量存在的范圍痢艺,在javascript中存在2種作用域:
(1)全局作用域:在全局作用域定義的變量稱為全局變量,全局作用域指變量在整個程序中都存在介陶,所有地方都可以讀鹊淌妗;
(2)函數(shù)作用域:在里面的定義的變量(需在定義變量的前面加上var哺呜,否則該變量會變?yōu)槿肿兞浚┓Q為局部變量舌缤,它們只函數(shù)內部存在;
作用域鏈的原理是某残,如果變量在該作用域中沒有国撵,則它會逐級向上尋找,直至最頂層玻墅。
*****
## 代碼
#### 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,'男');
/*
name:hunger
age:28
sex:男
["hunger",28,"男"]
name:valley
*/
getInfo('hunger',28);
/*
name:hunger
age:28
sex:undefined
["hunger",28]
name:vally
*/
getInfo('男');
/*
name:男
age:undefined
sex:undefined
["男"]
name:valley
*/
```
#### 2 寫一個函數(shù),返回參數(shù)的平方和澳厢?
```
function sumOfSquares(){
var sum = 0
for(var i=0;i<arguments.length;i++){
sum += arguments[i]*arguments[i];
}
console.log(sum);
}
sumOfSquares(2,3,4); //29
sumOfSquares(1,3); //10
```
#### 3 如下代碼的輸出环础?為什么囚似?
```
console.log(a); //undefined
var a = 1;
console.log(b); //報錯,b is not defined;
/*
由于變量的聲明提升喳整,所以在這段代碼執(zhí)行之前谆构,先聲明var a,在打印a,在
給a賦值框都,在打印b搬素,所以有上面的結果。
*/
```
#### 4 如下代碼的輸出魏保?為什么熬尺?
```
sayName('world'); //hello world
sayAge(10); //TypeError:undefined is not a function
function sayName(name){
console.log('hello ',name);
}
var sayAge = function(age){
console.log(age);
};
/*
函數(shù)聲明語句會前置,所以在聲明語句之前調用也可以谓罗,而函數(shù)表達式只是var sayAge;聲明提升了粱哼,
此時函數(shù)還沒有賦給他,還不是函數(shù)檩咱,所以調用的時候會報錯揭措。
*/
```
#### 5 如下代碼的輸出?為什么刻蚯?
```
function fn(){}
var fn = 3;
console.log(fn);//3
/*
變量提升var fn;提升至最前,然后聲明fn為函數(shù),再將3賦值fn覆蓋了函數(shù)绊含。
*/
```
#### 6 如下代碼的輸出?為什么炊汹?
```
function fn(fn2){
console.log(fn2);
var fn2 =3;
console.log(fn2);
console.log(fn);
function fn2(){
console.log('fnnn2');
}
}
fn(10);
/*
依次輸出:
function fn2(){
console.log('fnnn2');
}
**********
3
**********
function fn(fn2){
console.log(fn2);
var fn2 =3;
console.log(fn2);
console.log(fn);
function fn2(){
console.log('fnnn2');
}
}
原因:
由于變量聲明提升和函數(shù)聲明前置躬充,代碼執(zhí)行順序會變成這樣
function fn(fn2){
var fn2; 聲明變量,此時fn2為傳入的參數(shù)10
function fn2(){ fn2聲明為函數(shù)讨便,覆蓋掉10
console.log('fnnn2');
}
console.log(fn2); 輸出fn2 為函數(shù)
fn2 =3; 賦值3充甚,覆蓋掉函數(shù)
console.log(fn2); 輸出3
console.log(fn); 輸出函數(shù)fn
}
fn(10);
*/
```
#### 7 如下代碼的輸出?為什么霸褒?
```
var fn = 1;
function fn(fn){
console.log(fn);
}
console.log(fn(fn)); //TypeError:number is not a function
/*
代碼執(zhí)行順序為:
var fn;
function fn(fn){
console.log(fn);
}
fn = 1; fn不是函數(shù)伴找,所以輸出報錯。
*/
```
#### 8 如下代碼的輸出废菱?為什么疆瑰?
```
console.log(j); //undefined 聲明提升,未賦值
console.log(i); //undefined 聲明提升昙啄,未賦值
for(var i=10; i<10; i++){
var j = 100;
}
console.log(i); //10
console.log(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;
}
}
/*
輸出結果:
undefined
100
10
代碼的執(zhí)行順序:
var i;
var fn; 變量聲明提升
function fn(){ 函數(shù)聲明前置
var i; 函數(shù)中的變量聲明提升
function fn2(){ 函數(shù)聲明前置
i = 100;
}
console.log(i); i 未賦值梳凛;undefined
i = 99; i賦值99
fn2(); 執(zhí)行fn2(),i賦值100
console.log(i); 100
}
fn(); 執(zhí)行函數(shù)fn();
i = 10;
fn = 20;
console.log(i); i為10
*/
```
#### 10 如下代碼的輸出耿币?為什么?
```
var say = 0;
(function say(n){
console.log(n);
if(n<3) return;
say(n-1);
}( 10 )); //立即執(zhí)行函數(shù)韧拒,n=2時跳出函數(shù),不影響后續(xù)代碼淹接。
console.log(say); //0
/*
輸出結果:
10
9
8
7
6
5
4
3
2
0
*/
```