函數與作用域

聲明前置和作用域也是JS 部分面試常考點

1.函數聲明和函數表達式有什么區別

函數聲明:使用function關鍵字可以聲明一個函數。

 function sayHello(){
   console.log('hello')
 }
 //函數調用
 sayHello()```
聲明不必放到調用的前面,聲明的是一個函數,用時就是調用,該聲明位置可放在后面。函數聲明最重要的特征就是函數聲明提升,意思是在執行代碼之前就會讀取函數聲明。

函數表達式:用函數表達式定義的函數在使用之前必須先賦值。
 ```var sayHello = function(){
   console.log('hello');
 }
 sayHello()```
聲明必須放到調用的前面,聲明的是一個變量,必須聲明過后才能使用。


####2.什么是變量的聲明前置?什么是函數的聲明前置
- 變量的聲明前置:JavaScript引擎的工作方式是,先解析代碼,獲取所有被聲明的變量,然后再一行一行地運行。這造成的結果,就是所有的變量的聲明語句,都會被提升到代碼的頭部,然后給他初始值undefined,然后才逐句執行程序,這就叫做“變量提升”,也即“變量的聲明前置”。在一個作用域塊中,所有的變量都被放在塊的開始出聲明,但是變量的賦值不會提升。

- 函數的聲明前置:在一個作用域下,同var 聲明的變量一樣,function 聲明的函數也會前置。函數的聲明前置優先級高于變量的聲明前置。

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

####3.arguments 是什么
arguments 是一個類似數組的對象, 對應于傳遞給函數的參數。在函數內部,可以使用arguments對象獲取到該函數的所有傳入參數。arguments 對象僅在函數內部有效,在函數外部調用 arguments 對象會出現一個錯誤。
嚴格模式下,
1. arguments 不能通過程序語法被綁定(be bound)或賦值。
2.函數的 arguments 對象會保存函數被調用時的原始參數。arguments[i] 的值不會隨與之相應的參數的值的改變而變化,同名參數的值也不會隨與之相應的 arguments[i] 的值的改變而變化。
3.不再支持 arguments.callee。arguments.callee 是一個不可刪除屬性,而且賦值和讀取時都會拋出異常。

``` function printPersonInfo(name, age, sex){
   console.log(name);
   console.log(age);
   console.log(sex);
 }
可以寫為
function printPersonInfo(){
   console.log(arguments[0]);
   console.log(arguments[1]);
   console.log(arguments[2]);
 }```

####4.函數的"重載"怎樣實現
在 JS 中沒有重載,同名函數會覆蓋。 但可以在函數體針對不同的參數調用執行相應的邏輯。
```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.立即執行函數表達式是什么?有什么作用
立即執行函數通常有下面幾種寫法:
```(function fn0() {})();
(function fn1() {} ()); 
// 在數組初始化器內只能是表達式
[function fn2() {}];
// 逗號也只能操作表達式
1, function fn3() {};```

在Javascript中,一對圓括號“()”是一種運算符,跟在函數名之后,表示調用該函數。比如,print()就表示調用print函數。
作用:
一是不必為函數命名,避免了污染全局變量;
二是隔離作用域,IIFE內部形成了一個單獨的作用域,可以封裝一些外部無法讀取的私有變量。

####6.求n!,用遞歸來實現
```function fn1(i){
 if(i===1){
   return 1;
 }
 return i*fn1(i-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,'sex']  name valley
name:小谷  age:3  sex:undefined   ['小谷',3]  name valley
name:男  age:undefined   sex:undefined    ['男']  name valley

####8. 寫一個函數,返回參數的平方和?
```function sumOfSquare() {
   var result = 0;
   for(var i=0; i<arguments.length; i++){
     result+=arguments[i]*arguments[i];
   }
   return result;
}
var result = sumOfSquares(2,3,4)
var result2 = sumOfSquares(1,3)
console.log(result)  //29
console.log(result)  //10```

####9. 如下代碼的輸出?為什么
   ```console.log(a);
   var a = 1;
   console.log(b);```
輸出:
undefined /*因為變量聲明前置,var a,console.log(a)*/
b is not defined報錯 /*因為變量b沒有聲明*/

####10. 如下代碼的輸出?為什么
   ```sayName('world');
   sayAge(10);
   function sayName(name){
       console.log('hello ', name);
   }
   var sayAge = function(age){
       console.log(age);
   };```
輸出:
hello world /*函數聲明可以放在后面*/
sayAge is not a function報錯 /*聲明放在后面了變量沒定義,聲明必須放到調用的前面,聲明的是一個變量,必須聲明過后才能使用*/

####11. 如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
```var x = 10
bar() 
function foo() {
 console.log(x)
}
function bar(){
 var x = 30
 foo()
}```
輸出:10

```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  
}```

####12. 如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
```var x = 10;
bar() 
function bar(){
 var x = 30;
 function foo(){
   console.log(x) 
 }
 foo();
}```    

輸出:30

```globalContext{
 AO:{
   x:10
   bar:function
 },
   Scope:null
}
foo.[[scope]] = barContext.AO
bar.[[scope]] = globalContext.AO
barContext{
 AO:{
   x:30
   foo:function
 },
   Scope:bar.[[scope]] //globalContext.AO
}
fooContext{
 AO:{    
 },
   Scope:foo.[[scope]] // barContext.AO  
}```

####13. 以下代碼輸出什么? 寫出作用域鏈的查找過程偽代碼
```var x = 10;
bar() 
function bar(){
 var x = 30;
 (function (){
   console.log(x)
 })()
}```
輸出:30

```globalContext{
 AO:{
   x:10
   bar:function
 }
 Scope:null
}
bar.[[scope]] = globalContext.AO
barContext{
 AO:{
   x:30
 }
 Scope:bar.[[scope]]
}```


####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)```

輸出:
undefined
5
1
6
20
200

```globalContext{
 AO:{
   a:200
   fn:function
   fn3:function
 },
   Scope:null
}
fn.[[scope]] = globalContext.AO
fn2.[[scope]] = fnContext.AO
fn3.[[scope]] = globalContext.AO
fnContext{
 AO:{
   a:20
   fn2:function
 },
   Scope:fn.[[scope]] //globalContext.AO
}
fn2Context{
 AO:{ 
 },
   Scope:fn2.[[scope]] // fnContext.AO  
}
fn3Context{
 AO:{ 
 },
   Scope:fn3.[[scope]] // globalContext.AO  
}```
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容

  • 1. 函數聲明和函數表達式有什么區別 使用function關鍵字聲明一個函數時,聲明不必放到調用的前面。//函數聲...
    _李祺閱讀 278評論 0 0
  • 函數聲明和函數表達式有什么區別? 函數聲明和函數表達式是EMACScript規定的兩種不同的聲明函數的方法。1.函...
    LeeoZz閱讀 350評論 0 1
  • 1.函數聲明和函數表達式有什么區別 函數聲明不必放在調用前面 函數表達式必須放在調用前面 2.什么是變量的聲明前置...
    LINPENGISTHEONE閱讀 300評論 0 0
  • 1,函數聲明和函數表達式有什么區別 1、背景介紹 定義函數的方法主要有三種: 1:函數聲明(Function De...
    進擊的前端_風笑影閱讀 445評論 0 0
  • 今天1號店搬家,大家都很辛苦。 這兩天一直在考慮做計劃的事情,到了應該努力的時間段了。今天有一個關鍵詞經常會在我說...
    羅召偉閱讀 436評論 1 5