js-函數(shù)與作用域

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

  • 函數(shù)聲明:定義一個具有指定參數(shù)的函數(shù),函數(shù)聲明最重要的特征就是函數(shù)聲明提升,意思是在執(zhí)行代碼之前就會讀取函數(shù)聲明.

sayHi();
function sayHi(){
    alert("hi world");
}
//不會報錯,因為函數(shù)聲明在sayHi()在函數(shù)sayHi()之前已經(jīng)讀取

name :函數(shù)名
param:要傳遞給函數(shù)的參數(shù)的名稱。不同引擎中的最大參數(shù)數(shù)量不同。一個函數(shù)最多有255個參數(shù)
statements:包含函數(shù)體的語句。
描述:
一個被函數(shù)聲明創(chuàng)建的函數(shù)是一個 Function 對象,具有 Function 對象的所有屬性鞋诗、方法和行為。
參考

  • 函數(shù)表達式
    用函數(shù)表達式定義的函數(shù)在使用之前必須先賦值
sayHi();
var sayHi = function() {
    alert("hi wrold");
}
//報錯迈嘹,函數(shù)sayHi()調(diào)用之前并未賦值
  • 區(qū)別
    1 函數(shù)表達式定義的函數(shù)在使用之前必須先賦值,而函數(shù)聲明不必.
    2 函數(shù)表達式與函數(shù)聲明的最主要區(qū)別是函數(shù)名稱(function name)削彬,在函數(shù)表達式中可忽略它,從而創(chuàng)建匿名函數(shù).

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

  • 變量聲明前置就是在一個作用域塊中融痛,所有的變量都被放在塊的開始出聲明

1 var a = 1;
2 function main() {
3     console.log(a);//1
4 }
5 main();//輸出1

1 var a = 1;
2 function main() {
3     console.log(a);
4     var a = 2;
5 }
6 main()//輸出undefined

為什么輸出undefined,因為腳本在執(zhí)行的時候會自動將變量聲明前置

參考

  • 函數(shù)的聲明前置:在一個作用域下,同var 聲明的變量一樣神僵,function 聲明的函數(shù)也會前置雁刷。函數(shù)的聲明前置優(yōu)先級高于變量的聲明前置。

var a = 3;
console.log(a); //3
sayHello();
function sayHello(){
  console.log('hello');//hello
}
執(zhí)行時語句順序如下:
var a
function sayHello(){}
console.log(a);//undefined
a=3
console.log(a); //3
sayHello();

3 arguments 是什么?

  • arguments對象是所有函數(shù)中可用的局部變量,你可以使用arguments對象在函數(shù)中引用函數(shù)的參數(shù)保礼。此對象包含傳遞給函數(shù)的每個參數(shù)的條目沛励,第一個條目的索引從0開始。例如炮障,如果一個函數(shù)傳遞了三個參數(shù)目派,你可以參考它們?nèi)缦拢?/li>
arguments[0]
arguments[1]
arguments[2]

參數(shù)也可以被設置:
arguments[1] = 'new value';
arguments對象不是一個 Array它類似于數(shù)組

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

  • Javascript中,先定義的函數(shù)铝阐,可以被后定義的函數(shù)覆蓋址貌。因此Javascript不支持函數(shù)的重載。比如下面的例子:
<script type="text/javascript">  
       function p(a, b, c) {  
           alert(a+b+c);  
       }  
 
       function p(a, b) {  
           alert(a+b);  
       }  
       p(1,2,3);//alert 3;  
   </script>  

雖然有函數(shù)p(a, b, c)徘键,但是由于語言的特性,該函數(shù)被后面的p(a,b)所覆蓋

  • 但是利用js的arguments遍蟋,可以實現(xiàn)JavaScript的重載吹害。
    function showMessage(){
         if(arguments.length==1){
             console.log(arguments[0]);
         }else if( arguments.length==2){
             console.log(arguments[0]+"說:"+arguments[1]);
         }else{
             return false;
         }
     }
    showMessage("Hi!");
    showMessage("張三","Hi 你好"); 

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

  • 我們需要在定義函數(shù)之后虚青,立即調(diào)用該函數(shù).這時不能在函數(shù)的定義之后加上圓括號它呀,這會產(chǎn)生語法錯誤.

function(){ /* code */ }();
// SyntaxError: Unexpected token 

產(chǎn)生這個錯誤的原因是,function這個關(guān)鍵字即可以當作語句,也可以當作表達式纵穿。
// 語句
function f() {}
// 表達式
var f = function f() {}

為了避免解析上的歧義下隧,JavaScript引擎規(guī)定,如果function關(guān)鍵字出現(xiàn)在行首谓媒,一律解釋成語句淆院。因此,JavaScript引擎看到行首是function關(guān)鍵字之后句惯,認為這一段都是函數(shù)的定義土辩,不應該以圓括號結(jié)尾,所以就報錯了抢野。
解決方法就是不要讓function出現(xiàn)在行首拷淘,讓引擎將其理解成一個表達式。最簡單的處理指孤,就是將其放在一個圓括號里面启涯。

  • 通常情況下,只對匿名函數(shù)使用這種“立即執(zhí)行的函數(shù)表達式”恃轩。
    它的目的有兩個:一是不必為函數(shù)命名逝嚎,避免了污染全局變量;二是IIFE內(nèi)部形成了一個單獨的作用域详恼,可以封裝一些外部無法讀取的私有變量补君。
// 寫法一
var tmp = newData;
processData(tmp);
storeData(tmp);

// 寫法二
(function (){
  var tmp = newData;
  processData(tmp);
  storeData(tmp);
}());
上面代碼中,寫法二比寫法一更好昧互,因為完全避免了污染全局變量挽铁。

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


function jiechen(n) {
      if(n === 1){
      return 1;
    }
    return  n * jiechen(n-1);
}
 jiechen(4);//24

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, "男"]
name valley

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

name: 男
age: undefined
sex: undefined
["男"]
name valley
undefined


8 寫一個函數(shù)叽掘,返回參數(shù)的平方和?

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

    return sum;
}

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

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

    console.log(a);
    var a = 1;
    console.log(b);

輸出:
undefined //原因:變量聲明前置var a; 
"error" //沒有聲明變量b


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

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

輸出:
"hello  world"

"error"  //報錯原因:函數(shù)表達式定義的函數(shù)在使用之前必須先賦值.
改為如下:
var sayAge = function(age){
        console.log(age);
    };
sayAge(10);

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

var x = 10;
bar() ;
function foo() {
  console.log(x);
}
function bar(){
  var x = 30;
  foo();
}
輸出:10


原因:
全局作用域: {
   可使用變量:   x : 10
   可使用的函數(shù):  foo() , bar() 
}

foo()作用域: {
  可使用變量:   x : 10
}
bar()作用域: {
 可使用變量:   x : 30
 可使用的函數(shù):  foo()
}
運行邏輯:
先申明全局變量 x = 10;
執(zhí)行bar()函數(shù);
申明一個僅在bar()作用域內(nèi)訪問的局部變量x=30;
執(zhí)行foo()函數(shù),執(zhí)行console.log(x)方法;
但沒在當前作用域下找到?x變量,但全局作用域的x=10可以使用,完成輸出;


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

var x = 10;
bar();
function bar(){
  var x = 30;
  function foo(){
    console.log(x);//此處輸出30
  }
  foo();
}   
輸出:30


原因:
全局作用域: {
   可使用變量:   x : 10
   可使用的函數(shù):   bar() 
}

foo()作用域: {
  可使用變量:   x : 10
}
bar()作用域: {
 可使用變量:   x : 30
 可使用的函數(shù):  foo()
}
運行邏輯:
運行bar()-->運行 foo(), 找到可使用的局部變量x=30,輸出x=30;

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

var x = 10;
bar(); 
function bar(){
  var x = 30;
  (function (){
    console.log(x);
  })();
}
輸出:30
原因:
因為是立即調(diào)用函數(shù)所以上面代碼等價于下面的:
var x = 10;
bar(); 
function bar(){
  var x = 30;
  function fn(){
    console.log(x);
  };
  fn();
}
全局作用域{
可用變量:x=10 ;
函數(shù):bar()
}
bar()作用域{
可用變量 x=30
函數(shù):fn()
}


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

var a = 1;

function fn(){
  console.log(a);//第一次輸出:undefined:因為下面  var a = 5;所以提前申明了var a ;找不到a報錯.
  var a = 5;
  console.log(a);//第二次輸出5:因為在當前作用域下找到了a=5;
  a++;//a=6
  var a;
  fn3();
  fn2();
  console.log(a);//第五次輸出:20,因為a的值已經(jīng)在調(diào)用fn2()時被修改.

  function fn2(){
    console.log(a);//第四次輸出:6,因為這作用域里沒有var a 申明 ,去上一級即fn()里作用域找,此時a++后,a=6.所以輸出6.
    a = 20;//  給fn()里的變量a賦值為20.并保存在內(nèi)存里
  }
}

function fn3(){
  console.log(a);// 第三次輸出:1,因為fn3()屬于全局函數(shù),這里沒var a,就去全局找到var a =1
  a = 200; //找到了全局a ,在這一步給全局變量a 賦值為200.并保存在內(nèi)存里.
}

fn();
console.log(a);//第六次輸出:200,因為去全局找,而a的值已經(jīng)在調(diào)用fn3()時被修改.

輸出:
undefined
5
1
6
20
200

原因:
全局作用域{
  可用變量: a = 1
  可用函數(shù): fn() ; fn3(); ;
}
fn()作用域內(nèi){
  可用變量: a =5; 
  可用函數(shù):fn2()
}
fn2()作用域內(nèi){
  可用變量: a =20
}
fn3()作用域內(nèi){
  可用變量: a=200
}
運行邏輯:
代碼//后內(nèi)容:為解釋

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赫冬,一起剝皮案震驚了整個濱河市浓镜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌劲厌,老刑警劉巖膛薛,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異补鼻,居然都是意外死亡哄啄,警方通過查閱死者的電腦和手機雅任,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來咨跌,“玉大人沪么,你說我怎么就攤上這事⌒堪耄” “怎么了禽车?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長拳喻。 經(jīng)常有香客問我哭当,道長,這世上最難降的妖魔是什么冗澈? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任钦勘,我火速辦了婚禮,結(jié)果婚禮上亚亲,老公的妹妹穿的比我還像新娘彻采。我一直安慰自己,他們只是感情好捌归,可當我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布肛响。 她就那樣靜靜地躺著,像睡著了一般惜索。 火紅的嫁衣襯著肌膚如雪特笋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天巾兆,我揣著相機與錄音猎物,去河邊找鬼。 笑死角塑,一個胖子當著我的面吹牛蔫磨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播圃伶,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼堤如,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了窒朋?” 一聲冷哼從身側(cè)響起搀罢,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎炼邀,沒想到半個月后魄揉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡拭宁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年洛退,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杰标。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡兵怯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出腔剂,到底是詐尸還是另有隱情媒区,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布掸犬,位于F島的核電站袜漩,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏湾碎。R本人自食惡果不足惜宙攻,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望介褥。 院中可真熱鬧座掘,春花似錦、人聲如沸柔滔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽睛廊。三九已至形真,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間超全,已是汗流浹背咆霜。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留卵迂,地道東北人裕便。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像见咒,于是被迫代替她去往敵國和親偿衰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,092評論 2 355

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

  • 函數(shù)聲明和函數(shù)表達式有什么區(qū)別改览? 函數(shù)聲明和函數(shù)表達式是EMACScript規(guī)定的兩種不同的聲明函數(shù)的方法下翎。1.函...
    LeeoZz閱讀 350評論 0 1
  • 函數(shù)聲明和函數(shù)表達式有什么區(qū)別 JavaScript 中需要創(chuàng)建函數(shù)的話,有兩種方法:函數(shù)聲明宝当、函數(shù)表達式视事,各自寫...
    蕭雪圣閱讀 956評論 2 2
  • JavaScript中的函數(shù)運行在它們被定義的作用域里,而不是它們被執(zhí)行的作用域里庆揩。 函數(shù)聲明和函數(shù)表達式有什么區(qū)...
    畢子歌閱讀 393評論 0 0
  • 如題俐东,本文介紹函數(shù)與作用域的相關(guān)知識 1.函數(shù)聲明和函數(shù)表達式有什么區(qū)別 函數(shù)聲明:使用function關(guān)鍵字可以...
    hahahahaqwert閱讀 295評論 0 0
  • 1.函數(shù)聲明和函數(shù)表達式有什么區(qū)別 函數(shù)聲明 代碼執(zhí)行時函數(shù)聲明會被提升到最前執(zhí)行跌穗,所以函數(shù)的調(diào)用與函數(shù)聲明的順序...
    Feiyu_有貓病閱讀 379評論 0 0