函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別
- 使用function關(guān)鍵字可以聲明一個函數(shù)起宽,聲明不必放在調(diào)用前面赦颇;
- 函數(shù)表達(dá)式相當(dāng)于把一個函數(shù)當(dāng)做一個值蓬痒,賦值給一個變量舌涨,所以聲明必須放在調(diào)用前面斩例。
什么是變量的聲明前置羞延?什么是函數(shù)的聲明前置
在一個作用域下拷淘,var
聲明的變量和function
聲明的函數(shù)會前置
//代碼段如下撇他,因?yàn)樽兞康穆暶髑爸弥裣埃栽诖a段頂部有一條隱性的聲明 var a
console.log(a); //因?yàn)槁暶髦胁]有給a賦值誊抛,所以輸出為 undefined
var a = 1;
//代碼段如下,因?yàn)楹瘮?shù)的聲明前置整陌,所以在代碼段頂部有一條隱性的聲明 function a(){}
console.log(a); //因?yàn)槁暶髦兄皇且粋€空函數(shù)拗窃,所以輸出為 function a(){}
function a(){
console.log("hello");
};
arguments 是什么
arguments是獲取傳遞給函數(shù)所有參數(shù)的類數(shù)組對象瞎领,可以使用方括號語法來訪問每一個元素,也可以使用length屬性來確定傳遞進(jìn)函數(shù)的參數(shù)的個數(shù)随夸。
需要注意的是九默,如果定義了函數(shù)參數(shù),但沒有傳進(jìn)相應(yīng)的參數(shù)值宾毒,則沒有傳遞值的函數(shù)參數(shù)被自動賦予undefined值驼修。
函數(shù)的"重載"怎樣實(shí)現(xiàn)
JavaScript不能像強(qiáng)類型語言那樣實(shí)現(xiàn)函數(shù)重載,在定義兩個相同函數(shù)名的函數(shù)诈铛,后一個函數(shù)會將前一個覆蓋乙各,要實(shí)現(xiàn)類似的功能,可以通過檢查傳入函數(shù)中參數(shù)的不同執(zhí)行相應(yīng)的邏輯模擬重載癌瘾。
立即執(zhí)行函數(shù)表達(dá)式是什么觅丰?有什么作用
不需要顯示的調(diào)用函數(shù),在定義函數(shù)后就立即執(zhí)行的函數(shù)就是立即執(zhí)行的函數(shù)表達(dá)式妨退,它的作用是隔離作用域妇萄,不會產(chǎn)生任何全局變量。
立即執(zhí)行函數(shù)表達(dá)式的寫法有以下幾種:
(function(){
...
})();
(function(){
...
}());
求n!咬荷,用遞歸來實(shí)現(xiàn)
function factor(n) {
if (n === 1 || n === 0) {
return 1;
};
if (n < 0) {
return "負(fù)數(shù)沒有階乘";
};
return n * factor(n - 1);
};
factor(n);
以下代碼輸出什么冠句?
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
undefined*/
getInfo('小谷', 3);
/*name: 小谷
age: 3
sex: undefined
["小谷", 3]
name valley
undefined*/
getInfo('男');
/*name: 男
age: undefined
sex: undefined
["男"]
name valley
undefined*/
寫一個函數(shù),返回參數(shù)的平方和幸乒?
function sumSquare() {
var sum = 0;
for (i = 0; i < arguments.length; i++) {
sum = sum + arguments[i]*arguments[i];
};
return sum;
};
sumSquare();
如下代碼的輸出懦底?為什么
console.log(a);
var a = 1;
console.log(b);
/* 將代碼段聲明前置并重寫
var a;
console.log(a);
a = 1;
console.log(b);
所以輸出結(jié)果為
undefined
Uncaught ReferenceError: b is not defined */
如下代碼的輸出?為什么
sayName('world');
sayAge(10);
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
/* function sayName(name)是函數(shù)聲明罕扎,該函數(shù)的調(diào)用可以放在函數(shù)聲明前面聚唐,
而var sayAge = function(age)是一個函數(shù)表達(dá)式,調(diào)用必須放在后面腔召,所以代碼段的輸出如下:
hello world
Uncaught TypeError: sayAge is not a function*/
如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
var x = 10
bar()
function foo() {
console.log(x)
}
function bar(){
var x = 30
foo()
}
/*
globalContext = {
AO: {
x: 10
foo: function
bar: function
}
Scope: null
}
foo.[[scope]]: globalContext.AO
bar.[[scope]]: globalContext.AO
barContext = {
AO: {
x: 30
}
Scope: bar.[[scope]]: globalContext.AO
}
fooContext = {
AO: {}
Scope: foo.[[scope]]: globalContext.AO
}
根據(jù)上面的作用域鏈查找過程偽代碼杆查,可得console.log(x)的輸出為10 undefined,則foo()為10 undefined臀蛛,則bar()為10 undefined
*/
如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
var x = 10;
bar()
function bar(){
var x = 30;
function foo(){
console.log(x)
}
foo();
}
/*
globalContext = {
AO: {
x: 10
bar: function
}
Scope: null
}
bar.[[scope]]: globalContext.AO
barContext = {
AO: {
x: 30
foo: function
}
Scope: bar.[[scope]]: globalContext.AO
}
foo.[[scope]]: barContext.AO
fooContext = {
AO: {}
Scope: foo.[[scope]]: barContext.AO
}
根據(jù)上面的作用域鏈查找過程偽代碼亲桦,可得console.log(x)的輸出為30 undefined,則foo()為30 undefined浊仆,則bar()為30 undefined
*/
以下代碼輸出什么? 寫出作用域鏈的查找過程偽代碼
var x = 10;
bar()
function bar(){
var x = 30;
(function (){
console.log(x)
})()
}
/*
globalContext = {
AO: {
x: 10
bar: function
}
Scope: null
}
bar.[[scope]]: globalContext.AO
barContext = {
AO: {
x: 30
(function (){console.log(x)}): function
}
Scope: bar.[[scope]]: globalContext.AO
}
(function (){console.log(x)}).[[scope]]: bar.[[scope]]: globalContext.AO
(function (){console.log(x)}) = {
AO: {}
Scope: bar.[[scope]]: globalContext.AO
}
根據(jù)上面的作用域鏈查找過程偽代碼客峭,(function (){console.log(x)})()是一個立即執(zhí)行函數(shù)表達(dá)式,它的取值應(yīng)該在barContext中找抡柿,則x為30舔琅,console.log(x)的輸出為30 undefined,bar()為30 undefined
*/
以下代碼輸出什么沙绝? 寫出作用域鏈查找過程偽代碼
var a = 1;
function fn(){
console.log(a) //undefiend
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.[[scope]]: globalContext.AO
fn3.[[scope]]: globalContext.AO
執(zhí)行fn()函數(shù)時搏明,根據(jù)聲明前置鼠锈,在第一個console.log(a)執(zhí)行時,作用域鏈查找過程偽代碼如下:
fnContext = {
AO: {
a: undefined
fn2: function
}
Scope: fn.[[scope]]: globalContext.AO
}
fn2.[[scope]]: fnContext.AO
當(dāng)a=5時星著,作用域鏈查找過程偽代碼如下
fnContext = {
AO: {
a: 5
fn2: function
}
Scope: fn.[[scope]]: globalContext.AO
}
fn2.[[scope]]: fnContext.AO
當(dāng)執(zhí)行a++時购笆,作用域鏈查找過程偽代碼如下
fnContext = {
AO: {
a: 6
fn2: function
}
Scope: fn.[[scope]]: globalContext.AO
}
fn2.[[scope]]: fnContext.AO
執(zhí)行函數(shù)fn3()時,先代入fn3.[[scope]]: globalContext.AO中a的值虚循,輸出console.log(a)同欠,再重新對a賦值
fn3Context = {
AO: {
a: 200
}
Scope: fn3.[[scope]]: globalContext.AO
}
執(zhí)行fn3()后,全局上下文中a的值變?yōu)?00
執(zhí)行函數(shù)fn2()時横缔,先代入fn2.[[scope]]: fnContext.AO中a的值铺遂,輸出console.log(a),再重新對a賦值
fn2Context = {
AO: {
a: 20
}
Scope: fn2.[[scope]]: fnContext.AO
}
執(zhí)行fn2()后茎刚,fn()中a的值變?yōu)?0
根據(jù)上面的計算襟锐,最終的詳細(xì)輸出結(jié)果為:
fn()共輸出5個值,一一對應(yīng)為
第一個console.log(a) => undefined
第二個console.log(a) => 5
fn3() => 1
fn2() => 6
第三個console.log(a) => 20
代碼段最后一個console.log(a) => 200 undefined
*/