函數(shù)與作用域

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

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

函數(shù)聲明:使用function關(guān)鍵字可以聲明一個函數(shù)。

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

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


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

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

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

####3.arguments 是什么
arguments 是一個類似數(shù)組的對象, 對應(yīng)于傳遞給函數(shù)的參數(shù)。在函數(shù)內(nèi)部,可以使用arguments對象獲取到該函數(shù)的所有傳入?yún)?shù)。arguments 對象僅在函數(shù)內(nèi)部有效,在函數(shù)外部調(diào)用 arguments 對象會出現(xiàn)一個錯誤。
嚴格模式下,
1. arguments 不能通過程序語法被綁定(be bound)或賦值。
2.函數(shù)的 arguments 對象會保存函數(shù)被調(diào)用時的原始參數(shù)。arguments[i] 的值不會隨與之相應(yīng)的參數(shù)的值的改變而變化,同名參數(shù)的值也不會隨與之相應(yīng)的 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.函數(shù)的"重載"怎樣實現(xiàn)
在 JS 中沒有重載,同名函數(shù)會覆蓋。 但可以在函數(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ù)表達式是什么?有什么作用
立即執(zhí)行函數(shù)通常有下面幾種寫法:
```(function fn0() {})();
(function fn1() {} ()); 
// 在數(shù)組初始化器內(nèi)只能是表達式
[function fn2() {}];
// 逗號也只能操作表達式
1, function fn3() {};```

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

####6.求n!,用遞歸來實現(xià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. 寫一個函數(shù),返回參數(shù)的平方和?
```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 /*函數(shù)聲明可以放在后面*/
sayAge is not a function報錯 /*聲明放在后面了變量沒定義,聲明必須放到調(diào)用的前面,聲明的是一個變量,必須聲明過后才能使用*/

####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  
}```
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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