1.函數(shù)聲明和函數(shù)表達式有什么區(qū)別?
函數(shù)聲明:
function functionName(){ statement; }
函數(shù)表達式:
var printName = function(){ console.log('Byron'); };
對于函數(shù)聲明翠订,js解析器會優(yōu)先讀取(與變量提升類似,整個函數(shù)聲明也會預先解析
)捻撑,確保在所有代碼執(zhí)行之前聲明已經被解析幕侠。而函數(shù)表達式靶累,如同定義其它基本類型的變量一樣,定義變量名和賦值分兩個階段骂澄,定義變量名被提升吓蘑,函數(shù)賦值過程并沒有一起被提升。具體表現(xiàn)在坟冲,當使用函數(shù)聲明的形式來定義函數(shù)時磨镶,可將調用語句寫在函數(shù)聲明之前,而函數(shù)表達式健提,調用語句寫函數(shù)表達式前面會出錯琳猫。當聲明同一名稱的函數(shù)和變量時,變量聲明在函數(shù)聲明前面私痹,后面的函數(shù)聲明會覆蓋前面變量的聲明脐嫂。如果一個函數(shù)的聲明被括號括起來,此時是一個語句紊遵,函數(shù)聲明不會被提升(前置)由于JavaScript的這一怪異的“特性”账千,我們在函數(shù)內部定義變量時,請嚴格遵守“在函數(shù)內部首先申明所有變量”這一規(guī)則暗膜。最常見的做法是用一個var申明函數(shù)內部用到的所有變量
2.什么是變量的聲明前置匀奏?什么是函數(shù)的聲明前置 ?
【1】變量前置就是把變量的聲明提前到當前作用域的最前面桦山,但變量的賦值仍然按照原來的順序執(zhí)行攒射,如果變量聲明但未被賦值醋旦,變量會自動賦值為undefined。
【2】函數(shù)的聲明前置有兩種情況会放,一個是使用函數(shù)聲明饲齐,則整個聲明都前置,而且會被前置到變量聲明的后面咧最;另一個是使用函數(shù)表達式捂人,那么規(guī)則和變量的聲明前置一樣。
3.arguments 是什么矢沿?
函數(shù)中默認的arguments對象是獲取的函數(shù)在執(zhí)行中傳遞進函數(shù)的實際參數(shù)滥搭。arguments只在函數(shù)內部起作用,并且永遠指向當前函數(shù)的調用者傳入的所有參數(shù)捣鲸。arguments類似Array但它不是一個Array瑟匆。即使函數(shù)不定義任何參數(shù),arguments還是可以拿到參數(shù)的值栽惶。arguments常用來檢測傳遞進函數(shù)的參數(shù)個數(shù)愁溜。
4.函數(shù)的重載怎樣實現(xiàn) ?
靜態(tài)語言中相同名字的函數(shù)外厂,如果其參數(shù)個數(shù)不同或者參數(shù)順序不同都被認為是不同的函數(shù)冕象,稱為函數(shù)重載。在JavaScript中沒有函數(shù)重載的概念汁蝶,函數(shù)通過名字確定唯一性渐扮,參數(shù)不同也被認為是相同的函數(shù),后面的覆蓋前面的掖棉。JS函數(shù)重載用arguments來遍歷傳遞進函數(shù)的參數(shù)墓律。
5.立即執(zhí)行函數(shù)表達式是什么?有什么作用 幔亥?
函數(shù)立即執(zhí)行只锻,先括號聲明函數(shù)然后括號調用函數(shù)。
(function(){ })( )
(函數(shù)聲明)(函數(shù)調用)或者(function( ){ }( ))
立即執(zhí)行函數(shù)表達式一般不需要給函數(shù)命名紫谷,因為只需要立刻執(zhí)行并返回一個結果就行。函數(shù)立即執(zhí)行的作用:
1.不必為函數(shù)命名捐寥,避免了污染全局變量笤昨;
2.IIFE內部形成了一個單獨的作用域(因為加了括號成為了一個語句),可以封裝一些外部無法讀取的私有變量
6.什么是函數(shù)的作用域鏈 握恳?
【1】在大多數(shù)語言中都是用花括號{}來形成一個作用域瞒窒,俗稱塊作用域口蝠,但是在JavaScript中{ }并沒有帶來塊作用域奸焙,JavaScript的作用域是靠函數(shù)來形成的变抽,也就是說一個函數(shù)內定義的變量函數(shù)外不可以訪問
【2】函數(shù)內聲明變量加var代表局部變量蜻底,如果函數(shù)內聲明變量不加var,則聲明變量是全局變量拔稳。全局作用域的變量實際上是被綁定到window的一個屬性葛峻。
【3】由于JavaScript的函數(shù)可以嵌套,此時巴比,內部函數(shù)可以訪問外部函數(shù)定義的變量术奖,反過來則不行。任何變量(函數(shù)也視為變量)轻绞,如果沒有在當前函數(shù)作用域中找到采记,就會繼續(xù)往上查找,最后如果在全局作用域中也沒有找到政勃,則報ReferenceError錯誤唧龄。JavaScript的函數(shù)在查找變量時從自身函數(shù)定義開始,從“內”向“外”查找奸远。如果內部函數(shù)定義了與外部函數(shù)重名的變量既棺,則內部函數(shù)的變量將“屏蔽”外部函數(shù)的變量。
'use strict';
functionfoo() {
var x = 1; functionbar() {
var y = x + 1; // bar可以訪問foo的變量x!
}
var z = y + 1; // ReferenceError! foo不可以訪問bar的變量y!
}
7.以下代碼輸出什么然走?
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('男');
輸出結果:
getInfo('hunger', 28, '男'); //結果:
name:hunger
age:28
sex:男
["hunger",28,"男"]
name:valley
getInfo('hunger', 28); //結果:
name:hunger
age:28
sex:undefined
["hunger",28]
name:valley
getInfo( '男'); //結果:
name:男
age:undefined
sex:undefined
["男"]
name:valley
8.寫一個函數(shù)援制,返回參數(shù)的平方和?
functionsumOfSquares(){
var sum=0;
for(var i=0;i<arguments.length;i++){
sum=sum+arguments[i]*arguments[i];
}
return sum;
}
sumOfSquares(2,3,4); // 29
sumOfSquares(1,3); // 10
9.如下代碼的輸出芍瑞?為什么晨仑?
console.log(a); //undefined 聲明變量,變量提升 var a拆檬,還未執(zhí)行賦值洪己,所以a為undefined
var a = 1; //a=1; 執(zhí)行變量賦值,a=1;
console.log(b); //b is not defined b未聲明
10.如下代碼的輸出?為什么竟贯?
sayName('world'); // hello world 以函數(shù)聲明方式定義函數(shù)答捕,函數(shù)聲明提升,調用函數(shù)的語句可寫在函數(shù)聲明語句前
sayAge(10); //sayAge is not a function 以函數(shù)表達式方式定義函數(shù)屑那,類似變量提升拱镐,var sayAge為undefined所以調用函數(shù)時提示不是函數(shù)functionsayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
11.如下代碼的輸出?為什么持际?
functionfn(){} //先變量提升var fn沃琅,再函數(shù)提升var fn=function(){},因為同名所以此時函數(shù)提升覆蓋變量提升蜘欲,fn為函數(shù)
var fn = 3; //fn=3益眉,此時fn的值為3
console.log(fn); //輸出3
12.如下代碼的輸出?為什么?
functionfn(fn2){
console.log(fn2);
var fn2 = 3;
console.log(fn2);
console.log(fn);
functionfn2(){
console.log('fnnn2');
}
}
fn(10)輸出結果:
function fn2(){
console.log('fnnn2')
} //先分析參數(shù)再分析變量最后分析函數(shù)郭脂,因為同名年碘,所以函數(shù)聲明覆蓋活動對象中的參數(shù)、變量展鸡,打印函數(shù)fn2
3 //執(zhí)行fn2=3后 fn2的值為3
function fn(f2){
console.log(fn2);
var fn2 = 3;
console.log(fn2);
console.log(fn);
function fn2(){
console.log('fnnn2');
} //打印函數(shù)fn
}
13.如下代碼的輸出屿衅?為什么?
var fn = 1;
functionfn(fn){
console.log(fn);
}
console.log(fn(fn));
輸出結果:
fn is not a function
過程分析:首先變量提升娱颊,然后函數(shù)聲明覆蓋變量傲诵,再執(zhí)行變量賦值,所以fn值為1箱硕,用fn調用函數(shù)時會提示非函數(shù)拴竹。
14.如下代碼的輸出?為什么剧罩?
console.log(j); //函數(shù)順序執(zhí)行j未定義undefined
console.log(i); //函數(shù)順序執(zhí)行i未定義undefined
for(var i=0; i<10; i++){
var j = 100; //for循環(huán)中改變了i,j的值栓拜,i在循環(huán)后變?yōu)?0,每次循環(huán)時將j賦值為100
}
console.log(i); //i=10
console.log(j); //j=100
15.如下代碼的輸出惠昔?為什么幕与?
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
過程分析:函數(shù)順序執(zhí)行,先執(zhí)行fn(),fn中變量i被提升console.log(i)輸出undefined镇防,然后i賦值等于99啦鸣。再執(zhí)行fn2(),i=100,console.log(i)輸出100。最后執(zhí)行var i=10;fn=20,console.log(i)輸出結果為10.
16.如下代碼的輸出来氧?為什么诫给?
var say = 0;
(function say(n){
console.log(n);
if(n<3) return;
say(n-1);
}( 10 ));
console.log(say);
輸出結果是:
10
9
8
7
6
5
4
3
2
0
過程分析:函數(shù)被括號括起來,視為語句啦扬,整個函數(shù)聲明不會被前置中狂。先執(zhí)行var say--say=0--傳入?yún)?shù)10開始執(zhí)行say(n)函數(shù),打印10扑毡,9胃榕,8,7瞄摊,6勋又,5,4换帜,3赐写,2,當參數(shù)2滿足if條件時函數(shù)返回--再執(zhí)行console.log(say)打印0.