函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別
- 函數(shù)聲明必須有標(biāo)識符,也就是常說的函數(shù)名;函數(shù)表達(dá)式可以省略函數(shù)名。
- 函數(shù)聲明會提前,函數(shù)聲明的話函數(shù)可以提前調(diào)用,而函數(shù)表達(dá)式是什么時候遇到什么時候執(zhí)行。
- 以函數(shù)聲明的方法定義的函數(shù)并不是真正的聲明,它們僅僅可以出現(xiàn)在全局中,或者嵌套在其他的函數(shù)中,但是它們不能出現(xiàn)在循環(huán),條件或者try/catch/finally中,而函數(shù)表達(dá)式可以在任何地方聲明。
什么是變量的聲明前置?什么是函數(shù)的聲明前置?
變量提升:當(dāng)一個變量被定義時,在代碼執(zhí)行前會先將變量進(jìn)行初始化再執(zhí)行語句。函數(shù)提升:當(dāng)函數(shù)以函數(shù)聲明的方式聲明時,代碼執(zhí)行前會首先生成該函數(shù),然后再執(zhí)行語句。
arguments 是什么?
- 在函數(shù)代碼中,使用特殊對象 arguments,開發(fā)者無需明確指出參數(shù)名,就能訪問它們。
例如,在函數(shù) sayHi() 中,第一個參數(shù)是 message。用 arguments[0] 也可以訪問這個值,即第一個參數(shù)的值(第一個參數(shù)位于位置 0,第二個參數(shù)位于位置 1,依此類推)。 - 檢測參數(shù)個數(shù)
還可以用 arguments 對象檢測函數(shù)的參數(shù)個數(shù),引用屬性 arguments.length 即可。
模擬函數(shù)重載
函數(shù)的"重載"怎樣實(shí)現(xiàn)?
重載是很多面向?qū)ο笳Z言實(shí)現(xiàn)多態(tài)的手段之一,在靜態(tài)語言中確定一個函數(shù)的手段是靠方法簽名——函數(shù)名+參數(shù)列表,也就是說相同名字的函數(shù)參數(shù)個數(shù)不同或者順序不同都被認(rèn)為是不同的函數(shù),稱為函數(shù)重載。
在JavaScript中沒有函數(shù)重載的概念,函數(shù)通過名字確定唯一性,參數(shù)不同也被認(rèn)為是相同的函數(shù),后面的覆蓋前面的,但可以在函數(shù)體針對不同的參數(shù)調(diào)用執(zhí)行相應(yīng)的邏輯。
用 arguments 對象判斷傳遞給函數(shù)的參數(shù)個數(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á)式是什么?有什么作用?
定義一個函數(shù),然后立即調(diào)用它。
(function(){
var a = 1;
})()
其他寫法:
(function fn1() {});
[function fn2() {}];
1, function fn3() {};
作用:隔離作用域。
求n!,用遞歸來實(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
寫一個函數(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)錯
//實(shí)際按照如下執(zhí)行,b沒有定義故報(bào)錯。
var a;
console.log(a);
a = 1;
console.log(b);
如下代碼的輸出?為什么
sayName('world');//輸出hello world,函數(shù)的聲明會被前置
sayAge(10);//報(bào)錯,函數(shù)的表達(dá)式會被忽略掉,更不會被前置
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
//hello world 10
如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
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 時 得到下面
foo.[[scope]] = globalContext.AO
//聲明 bar 時 得到下面
bar.[[scope]] = globalContext.AO
barContext{
AO:{
x = 30;
}
Scope:bar[[scope]];//globalContext.AO
}
fooContext{
AO:{ }
Scope:foo[[scope]];//globalContext.AO
}
如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
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 時 得到下面
foo.[[scope]] = barContext.AO
//聲明 bar 時 得到下面
bar.[[scope]] = globalContext.AO
barContext{
AO:{
x = 30;
foo:function;
}
Scope:bar[[scope]];//globalContext.AO
}
fooContext{
AO:{ }
Scope:foo[[scope]];//barContext.AO
}
以下代碼輸出什么? 寫出作用域鏈的查找過程偽代碼
var x = 10;
bar() //輸出30
function bar(){
var x = 30;
(function (){
console.log(x)
})()
}
//
globalContext{
AO:{
x = 10;
bar:function;
}
Scope:null;
}
//聲明 bar 時 得到下面
bar.[[scope]] = globalContext.AO
barContext{
AO:{
x = 30;
}
Scope:bar[[scope]];//globalContext.AO
}
以下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
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 時 得到下面
fn.[[scope]] = globalContext.AO
//聲明 fn2 時 得到下面
fn2.[[scope]] = fnContext.AO
//聲明 fn3 時 得到下面
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
}