函數與作用域

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

  • 函數聲明:function fn(){}; 函數表達式: var fn = function(){}
  • 區別: 1. 函數聲明必須有標識符,也就是常說的函數名;函數表達式可以省略函數名。2.函數聲明會提前。3.函數聲明語句可以出現在全局代碼中,或者內嵌在其他函數中,但是不能出現在循環、條件判、或者try/finally以及with語句中。4.可以創建一個函數表達式即刻執行。
(function(){
alert('博主的名字是:myvin 。');
})()

這樣可以使得全局變量不受局部變量的影響,保持全局的干凈

什么是變量的聲明前置?什么是函數的聲明前置

  • 解析器將當前作用域內聲明的所有變量放到作用域的開始處,但是,只有變量的聲明被前置了(值都為undefined),而賦值操作被保留在原處。
  • JavaScript解析器允許在函數聲明之前使用函數,此時不僅僅是函數名被前置了,整個函數定義也被前置了,所以就可以直接調用函數

arguments 是什么

  • ECMAScript中的參數內部是用一個數組bi表示的,在函數體內可以通過arguments對象來訪問這個參數數組,來獲取傳遞給函數的每一個參數。arguments對象知識與數組類似(不是Array的實例),可以用方括號語法訪問它的每一個元素,并且有length屬性得到長度。arguments的值永遠與對應命名參數的值保持同步。

函數的"重載"怎樣實現

  • ECMAScript沒有函數簽名,所以不可能實現重載。重名的函數自會被覆蓋。可以在函數中加判斷語句來模擬重載。例如根據判斷參數的長度來模擬重載:
function overLoading() {
  // 根據arguments.length,對不同的值進行不同的操作
  switch(arguments.length) {
    case 0:
      /*操作1的代碼寫在這里*/
      break;
    case 1:
      /*操作2的代碼寫在這里*/
      break;
    }
}

立即執行函數表達式是什么?有什么作用

  • 立即執行函數表達式是函數表達式(命名的或者匿名的),在創建后立即執行;實現方式有下面幾種:
    <pre><code>(function(){ /* code / }());
    (function(){ /
    code / })();
    // 括號和JS的一些操作符(如 = && || ,等)可以在函數表達式和函數聲明上消除歧義
    // 如下代碼中,解析器已經知道一個是表達式了,于是也會把另一個默認為表達式
    // 但是兩者交換則會報錯
    var i = function(){ return 10; }();
    true && function(){ /
    code / }();
    0, function(){ /
    code / }();
    // 如果你不怕代碼晦澀難讀,也可以選擇一元運算符
    !function(){ /
    code / }();
    ~function(){ /
    code / }();
    -function(){ /
    code / }();
    +function(){ /
    code / }();
    // 你也可以這樣
    new function(){ /
    code / }
    new function(){ /
    code */ }() // 帶參數</code></pre>
  • 它的目的有兩個:一是不必為函數命名,避免了污染全局變量;二是IIFE內部形成了一個單獨的作用域,可以封裝一些外部無法讀取的私有變量。

求n!,用遞歸來實現

function fn(n){
    if(n<=1){
      return 1;
}else{
   return n*fn(n-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('饑人谷', 2, '男');
getInfo('小谷', 3);
getInfo('男');

name,饑人谷
age,2
sex,男
["饑人谷", 2, "男", callee: function, Symbol(Symbol.iterator): function]
name,valley
name,小谷
age,3
sex,undefined
["小谷", 2, callee: function, Symbol(Symbol.iterator): function]
name,valley
name,男
age,undefined
sex,undefined
["男",callee: function, Symbol(Symbol.iterator): function]
name,valley


###寫一個函數,返回參數的平方和?

function sumOfSquares(){
var result = 0;
for(var i = 0;i < arguments.length;i++){
result += Math.pow(arguments[i],2)
}
return result;
}
var result = sumOfSquares(2,3,4)
var result2 = sumOfSquares(1,3)
console.log(result) //29
console.log(result2) //10

###如下代碼的輸出?為什么

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

-  輸出undefined并且報錯。由于變量聲明提前,所以第一句輸出undefined。因為b沒有聲明,所以第三句報錯

###如下代碼的輸出?為什么
sayName('world');
sayAge(10);
function sayName(name){
    console.log('hello ', name);
}
var sayAge = function(age){
    console.log(age);
};
-  輸出hello  world并報錯,因為函數聲明提前,所以調用可以放在函數聲明前面;函數表達式類似于變量聲明,在函數表達式前調用等于undefined(),所以會報錯

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

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

-  輸出10

function foo(){}
function bar(){}
var x
x =10
/*全局執行上下文
globalContext = {
AO:{
x:10,
foo():function,
bar():function
},
Scope:null
}
//聲明 foo 時 得到下面
foo.[[scope]] = globalContext.AO
//聲明 bar 時 得到下面
bar.[[scope]] = globalContext.AO
/
bar()
/
bar執行上下文
barContext = {
AO:{
x = 30
},
Scope: bar.[[scope]] //globalContext.AO
}
/
foo()
/
foo執行上下文
fooContext = {
AO:{},
foo.[[scope]] = globalContext.AO //找到a =10
}
*/

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

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

-  輸出30

function bar(){}
var x
x = 10
/*全局上下文
globalContext = {
AO:{
x : 10
bar() : function
},
Scope:null
//聲明 bar 時 得到下面
bar.[[scope]] = globalContext.AO
}
/
bar()
/
bar上下文
barContext = {
AO:{
x : 30
foo():function
},
Scope: bar.[[scope]] //globalContext.AO
//聲明 foo時 得到下面
foo.[[scope]] = barContext.AO
}
/
foo()
/
foo()上下文
fooContext = {
AO:{},
foo.foo.[[scope]] = barContext.AO //在barContext中找到下= 30
}
*/


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

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

-  輸出30

function bar(){}
var x
x = 10
/*gloabContext = {
AO:{
x;10,
bar():function
},
Scope:null
//bar.[[scope]]=gloabContext.AO

/
bar()
/

barContext = {
AO:{
x:30,
匿名函數:function
},
bar.[[scope]] = globalContext.AO
// 匿名函數[[scope]]=barContext.AO
}
*/
匿名函數是立即執行函數,在barContext.AO中找到x =30


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

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

function fn(){}
function fn3(){}
var a
a = 3
/globalContext = {
AO:{
a:3
fn():function,
fn3():function
},
Scope:null
//fn[[scope]]=globalContext.AO
//fn3[[scope]]=globalContext.AO
}
/
fn(){
function fn2(){}
var a
console.log(a) //輸出undefined
a = 5
console.log(a) //輸出5
a++ //a = 6
fn3() //輸出1 賦值globalContext.AO的a=200
fn2() //輸出6 賦值fnContext.AO的a=20
console.log(a) //輸出20
}
/fnContext = {
AO:{
fn2():function,
a:6
},
Scope:globalContext.AO
//fn2[[scope]]=fnContext.AO
}
/
/fn2Context = {
OA:{},
Scope:fnContext.AO //a未定義,在globalContext.AO中找到a=6
}
/
/fn3Context = {
OA:{},
Scope:globalContext.AO //a未定義,在globalContext.AO中找到a=1
}
/
console.log(a) //輸出200

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,885評論 6 541
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,312評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,993評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,667評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,410評論 6 411
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,778評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,775評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,955評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,521評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,266評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,468評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,998評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,696評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,095評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,385評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,193評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,431評論 2 378

推薦閱讀更多精彩內容

  • 1. 函數聲明和函數表達式有什么區別 使用function關鍵字聲明一個函數時,聲明不必放到調用的前面。//函數聲...
    _李祺閱讀 279評論 0 0
  • 1.函數聲明和函數表達式有什么區別。 函數聲明使用function來進行聲明,函數聲明提升,所以不論執行語句的位置...
    Rising_suns閱讀 301評論 0 0
  • 任務 函數聲明和函數表達式有什么區別答:函數聲明:function functionName(){}??函數表達式...
    mhy_web閱讀 422評論 0 0
  • JavaScript中的函數運行在它們被定義的作用域里,而不是它們被執行的作用域里。 函數聲明和函數表達式有什么區...
    畢子歌閱讀 406評論 0 0
  • 1. 函數聲明和函數表達式有什么區別 函數聲明和函數表達式都是聲明函數的方式 區別1 寫法:函數聲明 : fu...
    怎么昵稱閱讀 273評論 0 0