level-17

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

在javascript中,函數(shù)有兩種定義寫法,函數(shù)定義表達(dá)式和函數(shù)聲明,其例子分別如下所示:

var test = function(x){
    return x;
  }

  function test(x){
    return x;
  }

盡管函數(shù)定義表達(dá)式和函數(shù)聲明語句包含相同的函數(shù)名,并且都創(chuàng)建了新的函數(shù)對象,但是這二者卻有區(qū)別。
-函數(shù)聲明語句中的函數(shù)名是一個變量名,變量指向函數(shù)對象。
-函數(shù)定義表達(dá)式和通過var聲明變量一樣,其函數(shù)被提前到了腳本或函數(shù)的頂部,因此它在整個腳本和或函數(shù)內(nèi)都是可見的。這樣的話,只有函數(shù)變量聲明提前了,函數(shù)的初始化代碼仍然在原來的位置。但是使用函數(shù)聲明的話,函數(shù)名稱和函數(shù)體均提前了,即腳本中的函數(shù)和函數(shù)中嵌套的函數(shù)都會在當(dāng)前上下文中其它代碼之前聲明,也即可以在聲明一個函數(shù)之前調(diào)用它。
例如:

test(1);
  function test(x){
    console.log(x);
  }

上面代碼能正常執(zhí)行。輸出結(jié)果為1,這時候函數(shù)變量聲明提前了。相當(dāng)于

  function test(x){
    console.log(x);
  }
    test(1);

運(yùn)行不會報錯。
而對于

test(1);
  var test = function(x){
    console.log(x);
  }

而這時,只相當(dāng)于函數(shù)變量聲明提前了,函數(shù)的初始代碼仍然在原位。即:

var test;
test(1);
  test = function(x){
    console.log(x);
  }

當(dāng)運(yùn)行到test(1);的時候就會報錯.


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

-變量的聲明前置:
-所謂的變量聲明前置就是在一個作用域塊中,所有的變量都被放在塊的開始出聲明
例如:

var a=10;
  function v(){
     console.log(c);
      var c=100;
}
v();

這時候運(yùn)行v() 控制臺輸出 undefined;就是因為變量的聲明前置;上面代碼和下面代碼一致。

var a=10;
  function v(){
   var c;
    console.log(c);
      c=100;
}
v();

當(dāng)運(yùn)行到console.log(c)的時候變量c只是聲明了。還未定義。則會顯示undefied;

-函數(shù)的聲明前置
-函數(shù)的聲明前置和變量聲明前置類型。只是函數(shù)表達(dá)式并不會發(fā)生聲明前置。例如

console.log(typeof foo);
console.log(typeof bar);
console.log(typeof add);
//函數(shù)的聲明
function foo(){
 alert('foo');
}
//命名函數(shù)表達(dá)式
var bar = function(){
 alert('bar');
};
// 函數(shù)表達(dá)式-匿名函數(shù)
var add = function(a,b){
return a+b;
};

arguments 是什么

-arguments 是JavaScript里的一個內(nèi)置對象,有的函數(shù)都有屬于自己的一個arguments對象
-函數(shù)的 arguments 對象并不是一個數(shù)組,但是訪問單個參數(shù)的方式與訪問數(shù)組元素的方式相同。
例如:

function main(){
  for(var i=0;i<arguments.length;i++){
    console.log(arguments[i]);
}
}
main("21a",21,"one")

這樣就利用arguments對傳輸進(jìn)來的數(shù)據(jù)進(jìn)行遍歷。


函數(shù)的重載

-JS中不存在函數(shù)的重載,而C++,java中函數(shù)的重載時利用相同名稱的函數(shù),參數(shù)個數(shù)和參數(shù)順序的不同認(rèn)為是不同的函數(shù),稱之為函數(shù)的重載。
-在JS中,函數(shù)依據(jù)函數(shù)名稱確定唯一性,相同名稱函數(shù),后者會覆蓋前者(即使參數(shù)個數(shù)和參數(shù)順序不同.)


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

立即執(zhí)行函數(shù)表達(dá)式是 例如

(function sayHello() { 
alert("hello"); 
}() ); 
或者:
(function sayHello() { 
alert("hello"); 
}) (); 

其主要作用是:
-隔離作用域,當(dāng)函數(shù)執(zhí)行完,其內(nèi)部定義的變量就釋放了,不會與外部變量發(fā)生沖突;相當(dāng)于人為創(chuàng)建一個塊級作用域,而JS本身沒有塊級作用域。
-封裝一段代碼而不會引起而不會遺留任何全局變量,定義的變量都是立即執(zhí)行函數(shù)的局部變量;


什么是函數(shù)的作用域鏈?

當(dāng)代碼在執(zhí)行時候,會創(chuàng)建變量對象的一個作用域鏈。作用域鏈的用途,是保證對執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問。js沒有塊級作用域,只有函數(shù)作用域。
例如:

var color="blue";
function getColor(){
    var otherColor="red";
      function changeColor(){
       vae tempColor=otherColor;
              otherColor=color;
               color=tempColor;
//這里可以訪問 tempColor   otherColor  和color
}
changeColor();
// 這里可以訪問  otherColor,color
}
//這里只能訪問color
getColor();

代碼

1.以下代碼輸出什么? (難度**)

 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('hunger', 28, '男'); 
getInfo('hunger', 28); 
getInfo('男');
輸入getInfo('hunger', 28, '男'); 的時候輸出{
name:hunger;
age:28;
sex:男;
["hunger", 28, '男'];
name:valley;
}

輸入getInfo('hunger', 28); 的時候輸出{
name:hunger;
age:28;
sex:undefined;
["hunger", 28];
name:valley;
}
輸入getInfo('男');的時候輸出{
name:男;
age:undefined;
sex:undefined;
["男"];
name:valley;
}

2.寫一個函數(shù),返回參數(shù)的平方和?如 (難度**)

 function sumOfSquares(){ 
           var sum=null;
         for(var i=0;i<arguments.length;i++){
          sum+=(arguments[i]*arguments[i]);
}
           console.log (sum);
} 
sumOfSquares(2,3,4); // 29 
sumOfSquares(1,3); // 10

3..如下代碼的輸出?為什么 (難度*)

 console.log(a); 
var a = 1; 
console.log(b);
_________________________
console.log(a) //輸出 1
console.log(b)//報錯顯示b undefied.
因為發(fā)生了函數(shù)聲明前置,例子代碼與下面代碼相同:
var a;
console.log(a);
a=1;
console.log(b);

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

sayName('world'); 
sayAge(10); 
function sayName(name){ 
        console.log('hello ', name); 
} 
var sayAge = function(age){ 
         console.log(age); 
};
___________
會輸出 hello,world;
sayAge 報錯,顯示undefined
因為變量聲明和函數(shù)聲明會前置,但函數(shù)表達(dá)式不會前置:轉(zhuǎn)換后如下例所示:
  var sayage;
  function sayName(name){
      console.log('hello ', name);
  }
  sayName('world');
  sayAge(10);
  ayAge = function(age){
      console.log(age);
  };

5.如下代碼的輸出?為什么 (難度**)

 function fn(){} 
var fn = 3; 
console.log(fn);
————————
輸出3
var fn;
function fn(){};
fn=3;
console.log(fn);
相當(dāng)于先聲明一個變量fn,再創(chuàng)建一個函數(shù)fn,此時會覆蓋之前聲明的fn,然后 將3賦值給函數(shù)fn,最后輸出3

6..如下代碼的輸出?為什么 (難度***)

function fn(fn2){
   console.log(fn2);
   var fn2 = 3;
   console.log(fn2);
   console.log(fn);
   function fn2(){
        console.log('fnnn2');
    }
 }
fn(10);
___________
會輸出
function fn2(){
        console.log('fnnn2');
    }
------
3
----
function fn(fn2){
      var fn2;
      function fn2(){
           console.log('fnnn2');
       }
      console.log(fn2);
      fn2 = 3;
      console.log(fn2);
      console.log(fn);
    }
可以將上例函數(shù)轉(zhuǎn)換為:
  function fn(fn2){
      var fn2;
      function fn2(){
           console.log('fnnn2');
       }
      console.log(fn2);
      fn2 = 3;
      console.log(fn2);
      console.log(fn);
    }
當(dāng)輸入 fn(10)的時候。
遇到var fn2;  這時候 fn2等于10;
function fn2(){} 沒有被調(diào)用 跳過。
console.log(fn2);輸出函數(shù)fn2:
function fn2(){
console.log('fnn2')
}
然后將3賦值給fn2,
遇到console.log(fn2);輸出3
然后遇到console.log(fn)輸出 函數(shù) fn();

7.如下代碼的輸出?為什么 (難度***)

  var fn = 1;
  function fn(fn){
       console.log(fn);
  }
  console.log(fn(fn)); 
報錯fn undefied 
————————
var fu;
 function fn(fn){
       console.log(fn);
  }
fu=1;
console.log(fn(fn));
我不知道這樣解釋對不對。
因為當(dāng)函數(shù)和變量聲明前置,函數(shù)的聲明覆蓋了變量的聲明,最后1賦值給fu,這時候fu類型不是function而是number,這時候console.log(fn(fn)) 就報錯。顯示fn不是一個函數(shù)。

8.如下代碼的輸出?為什么 (難度**)

  console.log(j);//報錯 undefined
  console.log(i);//報錯 undefined
  for(var i=0; i<10; i++){
      var j = 100;
  }
  console.log(i);//10
  console.log(j); //100
___________
此處沒有 什么變量提升,所以開始console.log(j);和console.log(i)都會報錯
然后經(jīng)過一個for循環(huán)后 i=10 j=100。
而且不會隨著循環(huán)的結(jié)束而消失,。然后console.log(i)和console.log(j) 就為10 和100

9.如下代碼的輸出?為什么 (難度****)

fn();
var i = 10;
var fn = 20;
console.log(i);
function fn(){
    console.log(i);
    var i = 99;
    fn2();
    console.log(i);
    function fn2(){
        i = 100;
    }
}
------------
可轉(zhuǎn)換為:
  var i
  var fn
  function fn(){
    var i
    function fn2(){
        i = 100;
    }
      console.log(i);//undefined
      i = 99;
      fn2();
      console.log(i);//100
        }
  fn();
  i = 10;
  fn = 20;
  console.log(i);//10
前面直接跳過,到fn(),會執(zhí)行函數(shù)fn() 先聲明一個局部變量var.這里面開始并不會執(zhí)行fn2(){} 到console.log(i)。
因為這里i只是聲明了,并沒有定義,所有會得到undefined ;然后將99賦值給局部變量i.然后執(zhí)行fn2(),會得到一個變量I,由于沒有用var聲明,此處I 在fn()中有效,所有console.log(i)等于100。
然后將10賦值為變量i,20賦值給fn;
得到console.log(i) 為10.

10.如下代碼的輸出?為什么 (難度*****)

   var say = 0;
    (function say(n){
        console.log(n);
        if(n<3) return;
        say(n-1);
    }( 10 ));
    console.log(say);   
——————————
這里輸出10,9,8,7,6,5,4,3,2,0
因為函數(shù)為自執(zhí)行函數(shù),變量只在函數(shù)作用域內(nèi)生效,并不會影響到外面的變量。所以左后console.log(say)輸出0
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 問答: 1. 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 (*) 在日常的任務(wù)中,JavaScript主要使用下面兩種方式創(chuàng)建...
    小木子2016閱讀 388評論 0 0
  • 一、函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別?(*) ** 1.ECMAScript里面規(guī)定了三種聲明函數(shù)的方式**①構(gòu)造函...
    鴻鵠飛天閱讀 525評論 0 0
  • 1. 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 (*) 函數(shù)在JS中有三種方式來定義:函數(shù)聲明(function decla...
    進(jìn)擊的阿群閱讀 479評論 0 1
  • 繼承 一、混入式繼承 二、原型繼承 利用原型中的成員可以被和其相關(guān)的對象共享這一特性,可以實現(xiàn)繼承,這種實現(xiàn)繼承的...
    magic_pill閱讀 1,124評論 0 3
  • 作為天蝎座,我一般很少與人主動接觸,無論是和諧的生活還是看不順眼的撕逼,請原諒我把撕逼也稱作交流 。 四年的大學(xué)宿...
    藜木莜瑾閱讀 1,531評論 0 0

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