1.函數(shù)聲明和函數(shù)表達式的區(qū)別?
- 在ECMAScript中,創(chuàng)建函數(shù)的最常用的兩個方法是函數(shù)表達式和函數(shù)聲明,兩者期間的區(qū)別是有點暈,因為ECMA規(guī)范只明確了一點:函數(shù)聲明必須帶有標(biāo)示(Identifier)(就是大家常說的函數(shù)名稱),而函數(shù)表達式則可以省略這個標(biāo)示符:
- 函數(shù)聲明:
function 函數(shù)名稱(參數(shù):可選){函數(shù)體} - 函數(shù)表達式:
function 函數(shù)名稱(可選)(參數(shù):可選){函數(shù)體} - 小結(jié):
- 若不聲明函數(shù)的名稱,它就是函數(shù)表達式
- 若同時聲明了函數(shù)名稱,ECMAScript是通過上下文來區(qū)分的,如果function foo(){}是作為賦值表達式的一部分的話,例如:
var fun1=function foo(){},那它就是一個函數(shù)表達式。如果function foo(){}被包含在一個函數(shù)體內(nèi),或者位于程序的最頂部的話,那它就是一個函數(shù)聲明。 - 特殊的函數(shù)表達式,如:
(function foo(){})它是表達式的原因是因為括號 ()是一個分組操作符,它的內(nèi)部只能包含表達式,同理如,JSON字符串通常被包含在一個圓括號里:eval('(' + json + ')'),這樣做的原因就是因為分組操作符,也就是這對括號,會讓解析器強制將JSON的花括號解析成表達式。
2.什么是變量的聲明前置?什么是函數(shù)的聲明前置?
-
所謂的變量聲明前置就是在一個作用域塊中,所有的變量都被放在塊的開始出聲明,下面舉個例子你就能明白了
1.變量a 在函數(shù)外面
var a=1;
function fun1(){
console.log(a);// 1
}
main();//輸出 1var a = 1; function fun1(){ console.log(a); var a = 2; } main()//輸出undefined
2.同樣是變量a在函數(shù)外層,為什么出現(xiàn)undefined,這是因為JS在執(zhí)行時候,會自動將變量聲明前置,解析步驟如下:
var a=1;
function fun1(){
var a;// a 此時為undefined
console.log(a);//輸出結(jié)果為undefined
a=2;//a 被賦值為2,但沒有輸出
}
fun1();//undefined
- 和變量的聲明會前置一樣,函數(shù)聲明同樣會前置.
1.如果我們使用函數(shù)表達式那么規(guī)則和變量一樣;
console.log(fun1) //undefined
var fun1= function(){}
2.我們使用函數(shù)聲明的方式,那么即使函數(shù)寫在最后也可以在前面語句調(diào)用,前提是函數(shù)聲明部分已經(jīng)被下載到本地
fun1();//結(jié)果為1
function fun1(){
console.log(1); //1
}
3.arguments 是什么?
- arguments 是是JavaScript里的一個內(nèi)置對象,它很古怪,也經(jīng)常被人所忽視,但實際上是很重要的。所有主要的js函數(shù)庫都利用了arguments對象。所以agruments對象對于javascript程序員來說是必需熟悉的。所有的函數(shù)都有屬于自己的一個arguments對象,它包括了函所要調(diào)用的參數(shù)。他不是一個數(shù)組,如果用typeof arguments,返回的是'object'。雖然我們可以用調(diào)用數(shù)據(jù)的方法來調(diào)用arguments。比如length,還有index方法。但是數(shù) 組的push和pop對象是不適用的
- 在函數(shù)內(nèi)部,你可以使用arguments對象獲取到該函數(shù)的所有傳入?yún)?shù)
function info(name,sex,age){
console.log(name);//"小明"
console.log(sex);//"男"
console.log(age);//18
console.log(arguments[0]);//"小明"
console.log(arguments[1]);//"男"
console.log(arguments[2]);//18
console.log(arguments);//"小明","男",18
console.log(arguments.length)//3
}
info("小明","男",18);//
info("小明","男");// “小明”,“男”,undefined 2
瀏覽器輸出結(jié)果:
![3BXV%DI)S@R8EB2@$NL26F.png
4. 函數(shù)的重載怎樣實現(xiàn)
- 重載是很多面向?qū)ο笳Z言實現(xiàn)多態(tài)的手段之一,在靜態(tài)語言中確定一個函數(shù)的手段是靠方法簽名——函數(shù)名+參數(shù)列表,也就是說相同名字的函數(shù)參數(shù)個數(shù)不同或者順序不同都被認(rèn)為是不同的函數(shù),稱為函數(shù)重載
- 在JavaScript中沒有函數(shù)重載的概念,函數(shù)通過名字確定唯一性,參數(shù)不同也被認(rèn)為是相同的函數(shù),后面的覆蓋前面的
- 在js中,我們實現(xiàn)重載常用的方式有:
1、根據(jù)傳入?yún)?shù)的類型執(zhí)行不同的操作。
2、利用參數(shù)中特殊的參數(shù)值進行不同的操作。
3、根據(jù)參數(shù)的個數(shù)進行重載。
這里對第3種實現(xiàn)方式進行說明
function f(length) {
var len= arguments.length;
if(1 == len) {
var width = arguments[1];
alert("高為:"+length+",寬為:"+width);
} else {
alert("高為:"+length);
}
}
f(10);// 高為10
f(10,10);高為10,寬為10
你就可以給函數(shù)f()傳入一個參數(shù)也可以傳入兩個參數(shù)了
5. 立即執(zhí)行函數(shù)表達式是什么?有什么作用
- 立即執(zhí)行函數(shù)就是聲明一個匿名函數(shù),馬上調(diào)用這個匿名函數(shù)
- 立即執(zhí)行函數(shù)表達式有兩種寫法
- 第一種
(function(){ }()); - 第二種
(function(){ })();
- 只有一個作用:創(chuàng)建一個獨立的作用域。這個作用域里面的變量,外面訪問不到(即避免「變量污染」),例如:
var liList = ul.getElementsByTagName('li')
for(var i=0; i<6; i++){
liList[i].onclick = function(){
alert(i) // 為什么 alert 出來的總是 6,而不是0、
1、2、4、5
}
}
這是因為i貫穿了整個作用域,而在js中除了函數(shù)內(nèi)有作用域,{ }里的內(nèi)容不是作用域,因而for運行完后i的值為6,而用戶也是在for運行完才點擊,此時i為6。
解決整個問題就要立即執(zhí)行函給每個li創(chuàng)造獨立的作用域
var liList = ul.getElementsByTagName('li')
for(var i=0; i<6; i++){
!function(li){
liList[li].onclick = function(){
alert(li) // 0、1、2、3、4、5
}
}(i)
}
在立即執(zhí)行函數(shù)執(zhí)行的時候,i 的值被賦值給 ii,此后 ii 的值一直不變。i 的值從 0 變化到 5,對應(yīng) 6 個立即執(zhí)行函數(shù),這 6 個立即執(zhí)行函數(shù)里面的 ii 「分別」是 0、1、2、3、4、5。
6. 什么是函數(shù)的作用域鏈
- 作用域鏈?zhǔn)谴鎯?strong>變量對象的集合(環(huán)境棧),保證對執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問,也就是用于標(biāo)識符解析(變量訪問)。
- 在javascript沒有塊級作用域,是由函數(shù)來劃分的。變量和函數(shù)的作用域是在定義時決定而不是執(zhí)行時決定,也就是說詞法作用域取決于源碼,通過靜態(tài)分析就能確定,因此詞法作用域也叫做靜態(tài)作用域(with和eval除外)。當(dāng)定義了一個函數(shù),當(dāng)前的作用域鏈就保存起來,并且成為函數(shù)的內(nèi)部狀態(tài)的一部份。在最頂級作用域鏈僅由全局對象組成,而不和詞法作用域相關(guān),然而,當(dāng)定義一個嵌套的函數(shù)時,作用域鏈就包括外面的包含函數(shù)。這意味著嵌套函數(shù)可以訪問包含函數(shù)的所有參數(shù)和局部變量。盡管當(dāng)一個函數(shù)定義時作用域鏈就固定了,但作用域鏈中定義的屬性還沒有固定。作用域鏈?zhǔn)腔畹?,并且函?shù)被調(diào)用時,可以訪問任何當(dāng)前的綁定。
var a;//全局作用域
function b(){
var c ;//c位于函數(shù)b的作用域
function d(){
var e; //e位于函數(shù)d的作用域
alert(a);
}
} - 當(dāng)alert(a)時,jsJS引擎沿著d的作用域, b的作用域, 全局作用域的順序進行查找,這三個作用域組成的有序集合就成為作用域鏈