函數(shù)與作用域

1. 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別

  • 使用function關(guān)鍵字聲明一個(gè)函數(shù)時(shí),聲明不必放到調(diào)用的前面。
    //函數(shù)聲明 function sayHello(){ console.log('hello') } //函數(shù)調(diào)用 sayHello()
    函數(shù)表達(dá)式是把一個(gè)匿名函數(shù)function()賦給一個(gè)變量,聲明必須放到調(diào)用的前面。
    //函數(shù)聲明 var sayHello = function(){ console.log('hello'); } //函數(shù)調(diào)用 sayHello()
  • 函數(shù)聲明必須有標(biāo)識(shí)符,也就是常說(shuō)的函數(shù)名,函數(shù)表達(dá)式可以省略函數(shù)名。
  • 用函數(shù)聲明創(chuàng)建的函數(shù)可以隨時(shí)調(diào)用,而用函數(shù)表達(dá)式創(chuàng)建的函數(shù)是在運(yùn)行時(shí)進(jìn)行賦值,且要等到表達(dá)式賦值完成后才能調(diào)用。

2. 什么是變量的聲明前置?什么是函數(shù)的聲明前置

  • 在一個(gè)作用域下,var 聲明的變量和function 聲明的函數(shù)會(huì)前置
    console.log(a);//undefined
    var a = 3; console.log(a);//3
    sayHello(); function sayHello(){ console.log('hello'); }
    執(zhí)行順序?yàn)椋?br> var a function sayHello() console.log(a) //undefined
    a = 3 console.log(a) //3
    sayHello()
  • 函數(shù)內(nèi)部的聲明前置。
    var a = 1; function main() { console.log(a); var a = 2; } main()
    輸出undefined,函數(shù)的執(zhí)行順序如下,變量聲明被提前了。
    var a = 1; function main() { var a; console.log(a); //此時(shí)a為undefined
    a = 2; }
  • 解析器在向執(zhí)行環(huán)境加載數(shù)據(jù)時(shí),會(huì)率先讀取函數(shù)聲明,并使其在執(zhí)行任何代碼之前可用,所以存在函數(shù)聲明提升,對(duì)代碼求值的時(shí)候,js引擎在第一遍會(huì)聲明函數(shù)并將它們放到源代碼樹(shù)的頂部,所以即使調(diào)用函數(shù)的語(yǔ)句在聲明函數(shù)的前面也能正常執(zhí)行。但是對(duì)于函數(shù)表達(dá)式,它必須等到解析器執(zhí)行到它所在的代碼行,才會(huì)真正被解釋執(zhí)行。

3. arguments 是什么

arguments是一個(gè)類(lèi)數(shù)組對(duì)象,在函數(shù)內(nèi)部,可以使用arguments對(duì)象獲取到該函數(shù)的所有傳入?yún)?shù)。

4. 函數(shù)的"重載"怎樣實(shí)現(xiàn)

JS沒(méi)有重載! 同名函數(shù)會(huì)覆蓋。 但可以在函數(shù)體針對(duì)不同的參數(shù)調(diào)用執(zhí)行相應(yīng)的邏輯。例如:
function printPeopleInfo(name, age, sex){ if(name){ console.log(name); } if(age){ console.log(age); } if(sex){ console.log(sex); } } printPeopleInfo('Byron', 26); printPeopleInfo('Byron', 26, 'male');
可以在函數(shù)體內(nèi)部使用if語(yǔ)句,來(lái)根據(jù)傳遞的參數(shù),執(zhí)行不同的語(yǔ)句,來(lái)模擬函數(shù)的重載。

5. 立即執(zhí)行函數(shù)表達(dá)式是什么?有什么作用

表達(dá)式:(function(){ })();
立即執(zhí)行函數(shù)就是,聲明一個(gè)匿名函數(shù),馬上調(diào)用這個(gè)匿名函數(shù)。立即執(zhí)行函數(shù)可以創(chuàng)建一個(gè)獨(dú)立的作用域,這個(gè)作用域里面的變量,外面訪問(wèn)不到(即避免變量污染)。

6. 求n!,用遞歸來(lái)實(shí)現(xiàn)

function factor(n){ if(n === 1) { return 1 } return n * factor(n-1) } factor(5) n=5

7. 以下代碼輸出什么?

   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('男'); 
  • function getInfo(name, age, sex) { console.log('name:',name); console.log('age:', age); console.log('sex:', sex); } getInfo('饑人谷', 2, '男');結(jié)果://name: 饑人谷 age: 2 sex: 男
    getInfo('小谷', 3);結(jié)果://name: 小谷 age: 3 sex: undefined
    getInfo('男');結(jié)果://name: 男 age: undefined sex: undefined

  • function getInfo(name, age, sex) { console.log(arguments); } getInfo('饑人谷', 2, '男'); 結(jié)果:類(lèi)數(shù)組 ["饑人谷", 2, "男"]
    getInfo('小谷', 3); 結(jié)果:類(lèi)數(shù)組 ["小谷", 3]
    getInfo('男');結(jié)果:類(lèi)數(shù)組 ["男"]

  • function getInfo(name, age, sex) { arguments[0] = 'valley'; console.log('name', name); } getInfo('饑人谷', 2, '男'); 結(jié)果:name valley
    getInfo('小谷', 3); 結(jié)果:name valley
    getInfo('男'); 結(jié)果:name valley

8. 寫(xiě)一個(gè)函數(shù),返回參數(shù)的平方和?

  • function sumOfSquares(num1,num2,num3) { sum = num1*num1+num2*num2+num3*num3; return sum; } var result = sumOfSquares(2,3,4); console.log(result) //29

  • function sumOfSquares(num1,num2) { sum = num1*num1+num2*num2; return sum; } var result2 = sumOfSquares(1,3); console.log(result2) //10

9. 如下代碼的輸出?為什么

console.log(a); //結(jié)果:undefined
var a = 1;
console.log(b); //結(jié)果:報(bào)錯(cuò),b沒(méi)有定義。
因?yàn)樽兞柯暶鲿?huì)前置,實(shí)際順序如下:
var a console.log(a); a = 1; console.log(b);

10. 如下代碼的輸出?為什么

sayName('world'); //結(jié)果:hello world
sayAge(10); //結(jié)果:報(bào)錯(cuò),sayAge不是一個(gè)函數(shù)。
function sayName(name){ console.log('hello ', name); } var sayAge = function(age){ console.log(age); };
因?yàn)楹瘮?shù)聲明會(huì)前置,但函數(shù)表達(dá)式只會(huì)在執(zhí)行時(shí)才會(huì)運(yùn)行函數(shù),實(shí)際順序如下:
function sayName(name){ console.log('hello ', name); } //聲明函數(shù)
var sayAge //聲明變量
sayName("name") //調(diào)用函數(shù)
sayAge(10); // 調(diào)用函數(shù),但按順序函數(shù)還未聲明。
sayAge = function(age){ console.log(age); };

11. 如下代碼輸出什么? 寫(xiě)出作用域鏈查找過(guò)程偽代碼

var x = 10 bar() function foo() { console.log(x) } function bar(){ var x = 30 foo() }
結(jié)果:10
作用域鏈查找過(guò)程:
globalContext { AO: { x: 10, foo: function bar: function }, Scope: null }
//foo.[[scope]] = globalContext.AO
//bar.[[scope]] = globalContext.AO

barContext { AO: { x: 30 foo: function }, Scope: bar.[[scope]] }

fooContext { AO: {}, Scope: foo.[[scope]] }
console.log(x)先從foo 執(zhí)行上下文中的AO里找,找不到再?gòu)膄oo的[[scope]]里找,找到后即調(diào)用,所以 console.log(x)是 10

12. 如下代碼輸出什么? 寫(xiě)出作用域鏈查找過(guò)程偽代碼

var x = 10; bar() function bar(){ var x = 30; function foo(){ console.log(x) } foo(); }
結(jié)果:30
作用域鏈查找過(guò)程:
globalContext { AO: { x: 10 bar: function }, Scope: null } //bar.[[scope]] = globalContext.AO barContext { AO: { x: 30 foo: function }, Scope: bar.[[scope]] } //foo.[[scope]] = barContext.AO fooContext { AO: {}, Scope: foo.[[scope]] }
console.log(x)先從foo 執(zhí)行上下文中的AO里找,找不到再?gòu)膄oo的[[scope]]里找,即是bar的執(zhí)行上下文,所以 console.log(x)是 30

13. 以下代碼輸出什么? 寫(xiě)出作用域鏈的查找過(guò)程偽代碼

var x = 10; bar() function bar(){ var x = 30; (function (){ console.log(x) })() }
結(jié)果:30
作用域鏈的查找過(guò)程:
globalContext { AO: { x: 10 bar: function }, Scope: null } //bar.[[scope]] = globalContext.AO barContext { AO: { x: 30 function: function }, Scope: bar.[[scope]] } //function.[[scope]] = barContext.AO functionContext { AO: {}, Scope: function.[[scope]] }
console.log(x)先從function 執(zhí)行上下文中的AO里找,找不到再?gòu)膄unction的[[scope]]里找,即是bar的執(zhí)行上下文,所以 console.log(x)是 30

14. 以下代碼輸出什么? 寫(xiě)出作用域鏈查找過(guò)程偽代碼

var a = 1; function fn(){ console.log(a) //僅聲明,未賦值,undefined var a = 5 console.log(a) //賦值為5 a++ //自增變?yōu)? var a
fn3() //先執(zhí)行fn3里的console.log(a),為1
fn2() //再執(zhí)行fn2里的console.log(a),為6
console.log(a) //經(jīng)過(guò)fn2,a變?yōu)?0
function fn2(){ console.log(a) //即fnContext.AO = globalContext.AO中的a a = 20 } }
function fn3(){
console.log(a) //即globalContext.AO中的a
a = 200 //globalContext.AO中的a變?yōu)?00
}
fn()
console.log(a) //調(diào)用globalContext.AO中的a = 200
結(jié)果:
作用域鏈的查找過(guò)程:
globalContext { AO: { x: 1 fn: function fn3: function }, Scope: null } //fn.[[scope]] = globalContext.AO //fn3.[[scope]] = globalContext.AO fnContext { AO: { x: 1 //之后a賦值5,再之后a++
fn2: function }, Scope: fn.[[scope]] //即globalContext.AO } //fn2.[[scope]] = fnContext.AO fn3Context { AO: { }, Scope: fn3.[[scope]] //即globalContext.AO
}
結(jié)果:
undefined
5
1
6
20
200

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別。 函數(shù)聲明使用function來(lái)進(jìn)行聲明,函數(shù)聲明提升,所以不論執(zhí)行語(yǔ)句的位置...
    Rising_suns閱讀 373評(píng)論 0 0
  • 任務(wù) 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別答:函數(shù)聲明:function functionName(){}??函數(shù)表達(dá)式...
    mhy_web閱讀 447評(píng)論 0 0
  • 1,函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 1、背景介紹 定義函數(shù)的方法主要有三種: 1:函數(shù)聲明(Function De...
    進(jìn)擊的前端_風(fēng)笑影閱讀 488評(píng)論 0 0
  • JavaScript中的函數(shù)運(yùn)行在它們被定義的作用域里,而不是它們被執(zhí)行的作用域里。 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)...
    畢子歌閱讀 467評(píng)論 0 0
  • 1.函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 函數(shù)聲明不必放在調(diào)用前面 函數(shù)表達(dá)式必須放在調(diào)用前面 2.什么是變量的聲明前置...
    LINPENGISTHEONE閱讀 333評(píng)論 0 0

友情鏈接更多精彩內(nèi)容