進(jìn)階任務(wù)3 函數(shù)和作用域鏈 作業(yè)

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

函數(shù)聲明

使用 function 關(guān)鍵字聲明一個(gè)函數(shù)

//函數(shù)聲明
function sayHello(){
    console.log('hello')
}

//函數(shù)調(diào)用
sayHello()

聲明不必放到調(diào)用的前面,但是不要放到其它函數(shù)中谈况。

函數(shù)表達(dá)式

var sayHello = function(){
    console.log('hello');
}

sayHello()

<span style="color:red">用函數(shù)表達(dá)式聲明函數(shù)必須放到調(diào)用的前面鼎姐。</span>函數(shù)表達(dá)式是內(nèi)容為函數(shù)聲明的表達(dá)式寄疏,類似 a++ 為內(nèi)容為變量運(yùn)算的表達(dá)式尝蠕,而 a++ 需要事先聲明 a 且確定 a 的值华蜒,因此同理函數(shù)表達(dá)式聲明必須放置在調(diào)用的前面叭喜。

函數(shù)也是一種引用類型捂蕴,函數(shù)表達(dá)式的寫法就是把函數(shù)指針賦值給了 sayHello 變量闪幽。

為什么叫函數(shù)表達(dá)式?
因?yàn)楸磉_(dá)式其本質(zhì)是一個(gè)值委可,是一坨東西最終計(jì)算出一個(gè)結(jié)果即一個(gè)值着倾;而這種寫法就是將一坨東西賦值給變量卡者,就是將一個(gè)值賦值給變量崇决,所以稱為函數(shù)表達(dá)式恒傻。
函數(shù)聲明的寫法就不是表達(dá)式盈厘,而是單純函數(shù)的語句。




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

var 和 function 的聲明前置

在一個(gè)作用域下契吉,var 聲明的變量和 function 聲明的函數(shù)會(huì)前置.
首先將所有 var variableName 前置(不包括變量賦值部分)跳仿;
其次將所有 function functionName(){} 前置(包括函數(shù)定義部分)
例如:

console.log(a); //undefined
var a = 3;
console.log(a); //3

sayHello();

function sayHello(){
  console.log('hello');
}

代碼的實(shí)際的執(zhí)行順序?yàn)椋?/p>

var a;
function sayHello() { console.log('hello'); }

console.log(a);
a = 3
console.log(a);
sayHello()

3. arguments 是什么

在函數(shù)內(nèi)部,你可以使用arguments對象獲取到該函數(shù)的所有傳入?yún)?shù)

function printPersonInfo(name, age, sex){
    console.log(name);
    console.log(age);
    console.log(sex);
    console.log(arguments);
}   

arguments 是一個(gè)類數(shù)組對象捐晶,可用 arguments[0] 等來標(biāo)識(shí)各個(gè)參數(shù)菲语,也可以調(diào)用 length 屬性來顯示對象中屬性的數(shù)量,但是也沒有了一些數(shù)組的屬性惑灵。


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

C語言重載范例

int sum(int num1, int num2){
  return num1 + num2;
}

float sum(float num1, float num2){
  return num1 + num2;
}

sum(1, 2);
sum(1.5, 2.4);

在 JS 中

沒有重載! 同名函數(shù)會(huì)覆蓋山上。 但可以在函數(shù)體針對不同的參數(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');

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

(function(){
  var a  = 1;
})()
console.log(a); //undefined

作用: <span style="color:red">隔離作用域</span>泣棋,避免和全局變量發(fā)生沖突胶哲。
包裹函數(shù)定義語句的括號(hào)使得 JS 解析器認(rèn)為括號(hào)內(nèi)是一個(gè)表達(dá)式,而不是一個(gè)函數(shù)聲明語句鸯屿。

其他寫法

(function fn1() {});
 
// 在數(shù)組初始化器內(nèi)只能是表達(dá)式
[function fn2() {}];
 
// 逗號(hào)也只能操作表達(dá)式修赞,逗號(hào)兩邊也被認(rèn)為是表達(dá)式
1, function fn3() {};

// 勾邦!號(hào)也可以寫成立即表達(dá)式的方法
!function(){
    var a = 1;
}()

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

function recursive(n) {
    if (n == 1) {
        return 1;
    } else {
        return n * (n-1);
    }
}

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('男');

輸出:

name: 饑人谷
age: 2
sex: 男
["饑人谷",2,"男"] // 別漏了作字符串標(biāo)記的引號(hào)
name valley

name: 小谷
age: 3
["小谷",3]
name valley

name: 男
[男]
name valley

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

function sumOfSquares(){
    var sumOfSquares = 0;
    for(var i = 0; i < arguments.length; i++){
        sumOfSquares += arguments[i] * arguments[i];
    }
    return sumOfSquares;
}

var result = sumOfSquares(2,3,4)
var result2 = sumOfSquares(1,3)
console.log(result) //29
console.log(result) //10

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

console.log(a); // undefined
var a = 1;
console.log(b); // Uncaught ReferenceError

代碼的執(zhí)行順序?yàn)椋?/p>

var a;
console.log(a); //undefined稽坤,此時(shí)變量 a 已經(jīng)聲明,但是并未賦值,所以顯示 undefined摆马,表示未定義惩淳,此處目前沒有任何值
a = 1;
console.log(b); //Uncaught ReferenceError,此時(shí)出現(xiàn)了錯(cuò)誤棉磨,因?yàn)樽兞?b 并未被聲明频敛,所以 JS 解析器將會(huì)顯示出現(xiàn)了搓球


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

sayName('world');
sayAge(10);
function sayName(name){
    console.log('hello ', name);
}
var sayAge = function(age){
    console.log(age);
};

代碼實(shí)際執(zhí)行順序:

function sayName(name){
    console.log('hello ', name);
}

sayName('world'); 
// hello world
// 由于函數(shù)聲明會(huì)被前置到代碼首部发侵,所以此語句正常運(yùn)行
sayAge(10); 
// Uncaught TypeError
// 用函數(shù)表達(dá)式的方式來聲明函數(shù),JS 解析器會(huì)認(rèn)為這是一個(gè)表達(dá)式而非函數(shù)聲明
// 所以這樣聲明的函數(shù)不會(huì)被聲明前置
// 所以在調(diào)用 sayAge 時(shí) JS 解析器會(huì)認(rèn)為函數(shù)未被聲明,顯示錯(cuò)誤
var sayAge = function(age){
    console.log(age);
};

輸出:
hello world
Uncaught TypeError


11. 如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼

var x = 10
bar() 
function foo() {
  console.log(x)
}
function bar(){
  var x = 30
  foo()
}

12. 如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼

var x = 10;
bar() 
function bar(){
  var x = 30;
  function foo(){
    console.log(x) 
  }
  foo();
}
作用域鏈如下:
globalContext = {
    AO: {
        x: 10,
        bar: function
    }
    Scope: null
}
// 聲明 bar 函數(shù)時(shí)解取,生成其作用域鏈如下
bar.[[scope]] = globalContext.AO


barContext = {
    AO: {
        x: 30,
        foo: function
    }
    scope: globalContext
}
// 聲明 foo 函數(shù)時(shí),生成其作用域鏈如下
foo.[[scope]] = barContext.AO


fooContext = {
    AO: {}
    Scope: barContext.AO
}
查找過程:

Step1 聲明變量 x 并且賦值為10
Step2 聲明前置 bar 函數(shù),在其內(nèi)聲明 bar 域內(nèi)變量x 并賦值30,
聲明域內(nèi) foo 函數(shù)旧噪,并隨后執(zhí)行 foo 函數(shù)
Step3 代碼執(zhí)行 bar 函數(shù)陪毡,然后執(zhí)行 foo 函數(shù)妙色,foo 函數(shù)活動(dòng)對象 AO 中沒有 x,
通過其作用域鏈找到 bar 函數(shù)的活動(dòng)對象 AO,在其中找到 x 值為30定庵,然后輸出值為30


13. 以下代碼輸出什么? 寫出作用域鏈的查找過程偽代碼

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,
        immediatelyFunction
    }
    Scope: globalContext.AO
}


immediatelyFunctionContext = {
    AO:{}
    Scope: barContext.AO
}

執(zhí)行流程:
Step1 聲明變量 x 并賦值為10
Step2 前置聲明函數(shù) bar,在 bar 域內(nèi)聲明變量 x 并賦值30,聲明立即執(zhí)行函數(shù)
Step3 執(zhí)行 bar 函數(shù),然后執(zhí)行 bar 域內(nèi)立即執(zhí)行函數(shù)擎勘,其找到其作用域
為 barContext.AO, 然后輸出值為30


14. 以下代碼輸出什么? 寫出作用域鏈查找過程偽代碼

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)
作用域鏈如下:
globalContext = {
    AO: {
        a: 1,200(代碼執(zhí)行 fn3() 時(shí))
        fn: function,
        fn3: function   
    }
    Scope: null
}
fn.[[scope]] = globalContext.AO
fn3.[[scope]] = globalContext.AO


fnContext = {
    AO: {
        a: undefined(被聲明前置時(shí)),5(被賦值為5時(shí))且蓬,
           6(執(zhí)行++操作)豹障,20(被 fn2() 函數(shù)修改)
        fn2: function
    }
    Scope: globalContext.AO
}
fn2.[[scope]] = fnContext.AO


fn2Context = {
    AO: {
        a: 20
    }
    Scope = fnContext.AO
}


fn3Context = {
    AO: {
        a: 200  
    }
    Scope = globalContext.AO
}

解答
var a = 1;

function fn(){
    console.log(a) 
// 輸出第1行:undefined坞笙,此時(shí)輸出 a 的值是函數(shù) fn 作用域中的值梯澜,
// fn 函數(shù)已經(jīng)前置聲明變量 a,但是還未賦值,固輸出 undefined
    var a = 5
    console.log(a)
// 輸出第2行:5,此時(shí)輸出 a 的值是函數(shù) fn 作用域中 a 的值衙熔,
// 該作用域中變量 a 剛剛被賦值為5
    a++
    var a
    fn3()
// 輸出第3行:1脖隶,此時(shí)輸出 a 的值是是函數(shù) fn3 在其作用域鏈 
// globalContext.AO 即全局上下文中找到的婉称,在該作用域中 a 的值為1
    fn2()
// 輸出第4行:6科汗,此時(shí)輸出 a 的值是函數(shù) fn 作用域中 a 的值,剛剛執(zhí)行++操作
    console.log(a)
// 輸出第5行:20,此時(shí)輸出 a 的值是函數(shù) fn 作用域中 a 的值,剛剛在 fn2 中
// 被改變?yōu)?0
    function fn2(){
        console.log(a)
        a = 20
    }
}

function fn3(){
    console.log(a)
    a = 200
}

fn()

console.log(a)
// 輸出第6行:200谱姓,此時(shí)輸出 a 的值是全局上下文中 a 的值,在 fn3 中被改變?yōu)?00
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖甜攀,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彤敛,死亡現(xiàn)場離奇詭異玄糟,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蟹肘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門书释,熙熙樓的掌柜王于貴愁眉苦臉地迎上來芍耘,“玉大人钾军,你說我怎么就攤上這事〗练” “怎么了簿寂?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵常遂,是天一觀的道長圈匆。 經(jīng)常有香客問我跃赚,道長叹括,這世上最難降的妖魔是什么侠讯? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任焙压,我火速辦了婚禮蛔溃,結(jié)果婚禮上绰沥,老公的妹妹穿的比我還像新娘篱蝇。我一直安慰自己,他們只是感情好徽曲,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布零截。 她就那樣靜靜地躺著,像睡著了一般秃臣。 火紅的嫁衣襯著肌膚如雪涧衙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天甜刻,我揣著相機(jī)與錄音绍撞,去河邊找鬼。 笑死得院,一個(gè)胖子當(dāng)著我的面吹牛傻铣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播祥绞,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼非洲,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蜕径?” 一聲冷哼從身側(cè)響起两踏,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎兜喻,沒想到半個(gè)月后梦染,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡朴皆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年帕识,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片遂铡。...
    茶點(diǎn)故事閱讀 38,064評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡肮疗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出扒接,到底是詐尸還是另有隱情伪货,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布钾怔,位于F島的核電站碱呼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏宗侦。R本人自食惡果不足惜巍举,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望凝垛。 院中可真熱鬧懊悯,春花似錦、人聲如沸梦皮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽剑肯。三九已至捧毛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間让网,已是汗流浹背呀忧。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留溃睹,地道東北人而账。 一個(gè)月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像因篇,于是被迫代替她去往敵國和親泞辐。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1.函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 函數(shù)聲明 代碼執(zhí)行時(shí)函數(shù)聲明會(huì)被提升到最前執(zhí)行竞滓,所以函數(shù)的調(diào)用與函數(shù)聲明的順序...
    Feiyu_有貓病閱讀 370評論 0 0
  • 1.函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 (*) 函數(shù)聲明 函數(shù)表達(dá)式 函數(shù)聲明:函數(shù)調(diào)用可以發(fā)生在函數(shù)聲明之前,例如下...
    TimeLesser閱讀 388評論 4 4
  • 任務(wù) 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別答:函數(shù)聲明:function functionName(){}??函數(shù)表達(dá)式...
    mhy_web閱讀 412評論 0 0
  • 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 函數(shù)聲明語法:function functionName(arg0,arg1,ar...
    _Dot912閱讀 566評論 0 3
  • 我們學(xué)校今年的迎新晚會(huì)請來了許巍咐吼,八首歌,最后一首藍(lán)蓮花引爆全場商佑! 沒有什么能夠阻擋锯茄, 你對自由的向往, 天馬行空...
    暖冬zyc閱讀 412評論 2 2