函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別
- 函數(shù)聲明必須有標(biāo)識(shí)符突想,也就是常說(shuō)的函數(shù)名;函數(shù)表達(dá)式可以省略函數(shù)名婆排。
- 函數(shù)聲明會(huì)提前荷科,函數(shù)聲明的話函數(shù)可以提前調(diào)用,而函數(shù)表達(dá)式是什么時(shí)候遇到什么時(shí)候執(zhí)行席楚。
- 以函數(shù)聲明的方法定義的函數(shù)并不是真正的聲明咬崔,它們僅僅可以出現(xiàn)在全局中,或者嵌套在其他的函數(shù)中,但是它們不能出現(xiàn)在循環(huán)烦秩,條件或者try/catch/finally中垮斯,而函數(shù)表達(dá)式可以在任何地方聲明。
什么是變量的聲明前置只祠?什么是函數(shù)的聲明前置兜蠕?
變量提升:當(dāng)一個(gè)變量被定義時(shí),在代碼執(zhí)行前會(huì)先將變量進(jìn)行初始化再執(zhí)行語(yǔ)句抛寝。函數(shù)提升:當(dāng)函數(shù)以函數(shù)聲明的方式聲明時(shí)熊杨,代碼執(zhí)行前會(huì)首先生成該函數(shù)曙旭,然后再執(zhí)行語(yǔ)句。
arguments 是什么晶府?
- 在函數(shù)代碼中夷狰,使用特殊對(duì)象 arguments,開(kāi)發(fā)者無(wú)需明確指出參數(shù)名郊霎,就能訪問(wèn)它們。
例如爷绘,在函數(shù) sayHi() 中书劝,第一個(gè)參數(shù)是 message。用 arguments[0] 也可以訪問(wèn)這個(gè)值土至,即第一個(gè)參數(shù)的值(第一個(gè)參數(shù)位于位置 0购对,第二個(gè)參數(shù)位于位置 1,依此類推)陶因。 - 檢測(cè)參數(shù)個(gè)數(shù)
還可以用 arguments 對(duì)象檢測(cè)函數(shù)的參數(shù)個(gè)數(shù)骡苞,引用屬性 arguments.length 即可。
模擬函數(shù)重載
函數(shù)的"重載"怎樣實(shí)現(xiàn)楷扬?
重載是很多面向?qū)ο笳Z(yǔ)言實(shí)現(xiàn)多態(tài)的手段之一解幽,在靜態(tài)語(yǔ)言中確定一個(gè)函數(shù)的手段是靠方法簽名——函數(shù)名+參數(shù)列表,也就是說(shuō)相同名字的函數(shù)參數(shù)個(gè)數(shù)不同或者順序不同都被認(rèn)為是不同的函數(shù)烘苹,稱為函數(shù)重載躲株。
在JavaScript中沒(méi)有函數(shù)重載的概念,函數(shù)通過(guò)名字確定唯一性镣衡,參數(shù)不同也被認(rèn)為是相同的函數(shù)霜定,后面的覆蓋前面的,但可以在函數(shù)體針對(duì)不同的參數(shù)調(diào)用執(zhí)行相應(yīng)的邏輯廊鸥。
用 arguments 對(duì)象判斷傳遞給函數(shù)的參數(shù)個(gè)數(shù)望浩,即可模擬函數(shù)重載:
function doAdd() {
if(arguments.length == 1) {
alert(arguments[0] + 5);
} else if(arguments.length == 2) {
alert(arguments[0] + arguments[1]);
}
}
doAdd(10); //輸出 "15"
doAdd(40, 20); //輸出 "60"
立即執(zhí)行函數(shù)表達(dá)式是什么?有什么作用惰说?
定義一個(gè)函數(shù)磨德,然后立即調(diào)用它。
(function(){
var a = 1;
})()
其他寫(xiě)法:
(function fn1() {});
[function fn2() {}];
1, function fn3() {};
作用:隔離作用域助被。
求n!剖张,用遞歸來(lái)實(shí)現(xiàn)
function factor(n){
if(n > 1){
n = factor(n-1)*n
return(n)
}else{
return(n = 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('饑人谷', 2, '男');//name:饑人谷 age:2 sex:男 ["饑人谷", 2, "男"] name valley
getInfo('小谷', 3);//name:小谷 age:3 sex:undefined ["小谷", 3] name valley
getInfo('男');//name:男 age:undefined sex:undefined ["男"] name valley
寫(xiě)一個(gè)函數(shù)揩环,返回參數(shù)的平方和搔弄?
function sumOfSquares() {
var sum = 0;
for (i = 0;i<arguments.length;i++){
sum = arguments[i]*arguments[i] + sum;
}
console.log(sum);
}
var result = sumOfSquares(2,3,4)
var result2 = sumOfSquares(1,3)
console.log(result) //29
console.log(result2) //10
如下代碼的輸出?為什么
console.log(a);//undefined
var a = 1;
console.log(b);//報(bào)錯(cuò)
//實(shí)際按照如下執(zhí)行丰滑,b沒(méi)有定義故報(bào)錯(cuò)顾犹。
var a;
console.log(a);
a = 1;
console.log(b);
如下代碼的輸出倒庵?為什么
sayName('world');//輸出hello world,函數(shù)的聲明會(huì)被前置
sayAge(10);//報(bào)錯(cuò)炫刷,函數(shù)的表達(dá)式會(huì)被忽略掉擎宝,更不會(huì)被前置
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
//hello world 10
如下代碼輸出什么? 寫(xiě)出作用域鏈查找過(guò)程偽代碼
var x = 10
bar() //輸出10
function foo() {
console.log(x)
}
function bar(){
var x = 30
foo()
}
//
globalContext{
AO:{
x = 10;
foo:function;
bar:function;
}
Scope:null;
}
//聲明 foo 時(shí) 得到下面
foo.[[scope]] = globalContext.AO
//聲明 bar 時(shí) 得到下面
bar.[[scope]] = globalContext.AO
barContext{
AO:{
x = 30;
}
Scope:bar[[scope]];//globalContext.AO
}
fooContext{
AO:{ }
Scope:foo[[scope]];//globalContext.AO
}
如下代碼輸出什么? 寫(xiě)出作用域鏈查找過(guò)程偽代碼
var x = 10;
bar() //輸出30
function bar(){
var x = 30;
function foo(){
console.log(x)
}
foo();
}
//
globalContext{
AO:{
x = 10;
bar:function;
}
Scope:null;
}
//聲明 foo 時(shí) 得到下面
foo.[[scope]] = barContext.AO
//聲明 bar 時(shí) 得到下面
bar.[[scope]] = globalContext.AO
barContext{
AO:{
x = 30;
foo:function;
}
Scope:bar[[scope]];//globalContext.AO
}
fooContext{
AO:{ }
Scope:foo[[scope]];//barContext.AO
}
以下代碼輸出什么? 寫(xiě)出作用域鏈的查找過(guò)程偽代碼
var x = 10;
bar() //輸出30
function bar(){
var x = 30;
(function (){
console.log(x)
})()
}
//
globalContext{
AO:{
x = 10;
bar:function;
}
Scope:null;
}
//聲明 bar 時(shí) 得到下面
bar.[[scope]] = globalContext.AO
barContext{
AO:{
x = 30;
}
Scope:bar[[scope]];//globalContext.AO
}
以下代碼輸出什么? 寫(xiě)出作用域鏈查找過(guò)程偽代碼
var a = 1;
function fn(){
console.log(a)//聲明前置浑玛。輸出undefined
var a = 5
console.log(a)//輸出5
a++
var a
fn3()//輸出1
fn2()//輸出6
console.log(a)輸出20
function fn2(){
console.log(a)
a = 20
}
}
function fn3(){
console.log(a)
a = 200
}
fn()
console.log(a)//輸出200
//
globalContext{
AO:{
a = 1;
fn:function;
fn3:function;
}
Scope:null;
}
//聲明 fn 時(shí) 得到下面
fn.[[scope]] = globalContext.AO
//聲明 fn2 時(shí) 得到下面
fn2.[[scope]] = fnContext.AO
//聲明 fn3 時(shí) 得到下面
fn3.[[scope]] = globalContext.AO
fnContext{
AO:{
a = 5;
fn2:function;
}
Scope:bar[[scope]];//globalContext.AO
}
fn3Context{
AO:{
a = 200;
}
Scope:foo[[scope]];//globalContext.AO
}
fn2Context{
AO:{
a = 20;
}
Scope:foo[[scope]];//fnContext.AO
}