函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別
-
函數(shù)聲明(Function Declaration) 示例代碼:
function abc(){ //中間是操作 }
-
函數(shù)表達(dá)式(Function Expression) 示例代碼:
var abc=function(){ //中間是操作 }
區(qū)別:用函數(shù)聲明創(chuàng)建的函數(shù)可以在函數(shù)解析后調(diào)用(解析時(shí)進(jìn)行等邏輯處理)尖昏;而用函數(shù)表達(dá)式創(chuàng)建的函數(shù)是在運(yùn)行時(shí)進(jìn)行賦值,且要等到表達(dá)式賦值完成后才能調(diào)用。通俗點(diǎn)講:函數(shù)聲明不是必須放到調(diào)用的前面拉讯;函數(shù)表達(dá)式的調(diào)用必須在賦值(聲明)之后又厉。
什么是變量的聲明前置馆衔?什么是函數(shù)的聲明前置
在同一個(gè)作用域下椒楣,var聲明的變量和function聲明的函數(shù)會(huì)前置恢总。
js代碼加載時(shí)候按照這樣的規(guī)則:遇到var聲明變量或者function聲明函數(shù),無論賦值與否巢掺,首先執(zhí)行給他們定義的操作句伶。前置順序從上到下,先前置陆淀,再賦值考余。
arguments 是什么
arguments 是JavaScript里的一個(gè)內(nèi)置對(duì)象,所有主要的js函數(shù)庫都利用了arguments對(duì)象轧苫。
所有的函數(shù)都有屬于自己的一個(gè)arguments對(duì)象楚堤,它包括了函所要調(diào)用的參數(shù)。他不是一個(gè)數(shù)組浸剩,如果用typeof arguments钾军,返回的是’object’。雖然我們可以用調(diào)用數(shù)據(jù)的方法來調(diào)用arguments绢要。比如length,還有index方法吏恭。但是數(shù)組的push和pop對(duì)象是不適用的。
函數(shù)的"重載"怎樣實(shí)現(xiàn)
首先簡單描述一下編程中函數(shù)的重載的理解:代碼里可以定義多個(gè)同名函數(shù)重罪,根據(jù)傳入的參數(shù)的方式不同樱哼,可以自動(dòng)去匹配所需要的函數(shù)。
然而在js里面剿配,沒有重載的概念搅幅。同名的函數(shù)會(huì)被覆蓋掉。但可以在函數(shù)體針對(duì)不同的參數(shù)調(diào)用執(zhí)行相應(yīng)的邏輯呼胚。
-
js中實(shí)現(xiàn)"重載"可以定義一個(gè)函數(shù)茄唐,通過判斷函數(shù)的參數(shù)來實(shí)現(xiàn)"重載",例如:
function abc(a,b,c) { if(a){ console.log(a) } if(b){ console.log(b) } if(c){ console.log(c) } }
立即執(zhí)行函數(shù)表達(dá)式是什么?有什么作用
立即自行函數(shù)表達(dá)式是一種立即調(diào)用函數(shù)的寫法沪编,通過函數(shù)表達(dá)式的方式聲明函數(shù)并直接調(diào)用呼盆。例如:
(function(){
console.log("我是立即執(zhí)行的函數(shù)表達(dá)式!")
}())
作用:不必為函數(shù)命名蚁廓,避免了污染全局變量访圃;立即執(zhí)行函數(shù)表達(dá)式內(nèi)形成了一個(gè)單獨(dú)的作用域,可以封裝一些外部無法讀取的私有變量相嵌。
求n!腿时,用遞歸來實(shí)現(xiàn)
function diGui(n) {
if(n===1){
return 1
}else{
return n = n*diGui(n-1)
}
}
diGui(10)
以下代碼輸出什么?
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('饑人谷', 2, '男');
getInfo('小谷', 3);
getInfo('男');
輸出結(jié)果如下:
ame: 饑人谷
age: 2
sex: 男
Arguments[3]
name valley
name: 小谷
age: 3
sex: undefined
Arguments[2]
name valley
name: 男
age: undefined
sex: undefined
Arguments[1]
name valley
寫一個(gè)函數(shù)饭宾,返回參數(shù)的平方和批糟?
function sumOfSquares(){
var sum = 0; //定義sum
for(i = 0; i < arguments.length; i++){
sum += arguments[i]*arguments[i]; //遍歷參數(shù)進(jìn)行平方和累加
}
return sum;
}
var result = sumOfSquares(2,3,4)
var result2 = sumOfSquares(1,3)
console.log(result) //29
console.log(result2) //10
如下代碼的輸出?為什么
console.log(a);
var a = 1;
console.log(b);
對(duì)以上代碼做變量提升
var a
console.log(a); //a沒有賦值捏雌,所以打印出undefined
a = 1
console.log(b);//b沒有聲明跃赚,所以會(huì)報(bào)錯(cuò)
如下代碼的輸出?為什么
sayName('world');
sayAge(10);
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
輸出結(jié)果只有hello world性湿,因?yàn)楹瘮?shù)聲明中函數(shù)調(diào)用可以放在聲明前,
函數(shù)表達(dá)式中函數(shù)必須先聲明满败,后調(diào)用肤频。
如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
var x = 10
bar()
function foo() {
console.log(x)
}
function bar(){
var x = 30
foo()
}
-
函數(shù)作用域鏈
1. globalContext = { AO: { x: 10 foo:function bar:function } Scope: null } //聲明foo時(shí)得到下面 foo.[[scope]] = globalContext.AO //聲明bar時(shí)得到下面 bar.[[scope]] = globalContext.AO //PS: 在當(dāng)前的執(zhí)行上下文內(nèi)聲明的函數(shù),這個(gè)函數(shù)的[[scope]]就執(zhí)行當(dāng)前執(zhí)行上下文的 AO 2. barContext: AO: { x:30;// 必須是var x =30才有 } Scope: bar.[[scope]] = globalContext.AO 3. fooContext: AO: {} Scope:foo.[[scope]] = globalContext.AO
根據(jù)函數(shù)作用域鏈來分析代碼算墨,首先定義了一個(gè)全局變量x:10宵荒,執(zhí)行函數(shù)bar(),在bar()函數(shù)中定義了局部變量x:30,調(diào)用函數(shù)foo()净嘀,執(zhí)行console.log(x),x的值首先在fooContex的AO中尋找报咳,AO中沒有,再到Scope中尋找挖藏,得出x:10暑刃,所以最終打印結(jié)果為10
如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
var x = 10;
bar()
function bar(){
var x = 30;
function foo(){
console.log(x)
}
foo();
}
-
函數(shù)作用域鏈
1.globalContext = { AO: { x: 10 bar:function } Scope:null } 2.barContext = { AO: { x: 30 foo: function } Scope: bar.[[scope]] = globalContext.AO } 3.fooContext = { AO: {} Scope: foo.[[scope]] = barContext.AO }
執(zhí)行console.log(x)時(shí),在fooContext中尋找x的值膜眠,AO中沒有聲明x的值岩臣,繼續(xù)指向barContext.AO,x取值為30,所以最終結(jié)果為30
以下代碼輸出什么? 寫出作用域鏈的查找過程偽代碼
var x = 10;
bar()
function bar(){
var x = 30;
(function (){
console.log(x)
})()
}
-
函數(shù)作用域鏈
1.globalContext = { AO: { x: 10 bar: function } Scope: null } 2.barContext = { AO: { x: 30 (): function } Scope: bar.[[scope]] = globalContext.AO } 3.()Context = { AO:{} Scope: ().[[scope]] = barContext.AO }
輸出結(jié)果為30
以下代碼輸出什么宵膨? 寫出作用域鏈查找過程偽代碼
var a = 1;
function fn(){
console.log(a)
var a = 5
console.log(a)
a++
var a
fn3()
fn2()
console.log(a)
function fn2(){
console.log(a)
a = 20
}
}
function fn3(){
console.log(a)
a = 200
}
fn()
console.log(a)
-
函數(shù)作用域鏈
1.globalContext = { AO: { a: 1 fn: function fn3: function } Scope:null } 2.fnContext = { AO: { a: 6 } Scope: fn.[[scope]] = globalContext.AO } 3.fn2Context = { AO: { a: 20 } Scope: fn2.[[scope]] = fnContext.AO } 4.fn3Context = { AO: { a: 200 } Scope: fn3.[[scope]] = globalContext.AO }
輸出結(jié)果為:undefined,5,1,6,20,200