一、函數聲明和函數表達式有什么區別 ?
答:
- 函數聲明:function fn(){}
- 函數表達式:var fn = function(){};
區別:1.函數聲明語句不能出現在if語句,while循環和其他任何語句中,表達式則可以;2.函數聲明會產生函數的聲明前置,因此可以在函數聲明之前就調用函數。函數表達式只會產生變量的聲明前置,因此在函數表達式之前調用會報錯。
二、什么是變量的聲明前置?什么是函數的聲明前置?
答:
- 變量的聲明前置,JavaScript代碼在解析時,會首先獲取所有被聲明的變量(只有變量名,不包含其值),使所有變量的聲明語句會提升到代碼的頭部。
- 函數的聲明前置,JavaScript代碼在解析時,先獲取所有被聲明的函數,使函數在執行任何代碼之前都可以訪問。
三、arguments是什么?
答:rguments 是一個類數組對象,相當于傳入的所有函數的集合,可以使用方括號語法訪問它的每一個元素。
四、函數的重載怎樣實現?
以下是重載的求和函數:
function sum(a,b,c){
var sum =0;
for (var i =0; i<arguments.length; i++){
sum += arguments[i];
}
return sum;
}
五、立即執行函數表達式是什么?有什么作用
(function() {code} (可傳入參數) );
(function () {code})(可傳入參數);
可以讓函數在定義后直接調用,作用是在固有的作用域內使用,不會污染全局變量。
六、什么是函數的作用域鏈
作用域:指對變量存在的范圍,在javascript中存在2種作用域:
(1)全局作用域:在全局作用域定義的變量稱為全局變量,全局作用域指變量在整個程序中都存在,所有地方都可以讀取;
(2)局部作用域:在里面的定義的變量(需在定義變量的前面加上var,否則該變量會變為全局變量)稱為局部變量,它們只函數內部存在;
作用域鏈的原理是,如果變量在該作用域中沒有,則它會逐級向上尋找,直至最頂層
代碼問答:
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 寫一個函數,返回參數的平方和?
function sumOfSquares(){
var sum =0;
for(var i=0;i<arguments.length; i++){
sum =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;
/*
由于變量的聲明提升,所以在這段代碼執行之前,先聲明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);
};
/*
函數聲明語句會前置,所以在聲明語句之前調用也可以,而函數表達式只是
var sayAge;聲明提升了,
此時函數還沒有賦給他,還不是函數,所以調用的時候會報錯。
*/
5.如下代碼的輸出?為什么 (難度**)
function fn(){}
var fn = 3;
console.log(fn);//3
/*
變量提升var fn;提升至最前,然后聲明fn為函數,再將3賦值fn覆蓋了函數。
*/
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');
}
}
原因:
由于變量聲明提升和函數聲明前置,代碼執行順序會變成這樣
7 如下代碼的輸出?為什么?
var fn = 1;
function fn(fn){
console.log(fn);
}
console.log(fn(fn));
因為fn是1不是函數所以報錯
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;100
原因:第一個輸出的是函數里面的第一個console.log(i),i還未賦值;
第二個輸出的是函數里面的第二個console.log(i),此時i由于fn2函數以賦
值100;
第三輸出的是函數外面的console.log(i),以被賦值10.
10.如下代碼的輸出?為什么 (難度*****)
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;
}
}
輸出結果:10,9,8,7,6,5,4,3,2,0
原因:立即執行函數,n=2時跳出函數,不影響后續代碼。