Day18-JS函數(shù)詳解(二)

  • ==1.函數(shù)的用法==
  • 復(fù)用代碼(略)
  • 把函數(shù)作為數(shù)據(jù)/值使用
  • 把函數(shù)作為命名空間使用
  • ==2. 作用域|變量提升 ==
  • 變量作用域
  • 變量聲明提升
  • 做題思路
  • ==3. 閉包==
  • 閉包

函數(shù)的用法

  • 用法1:復(fù)用代碼〔醣粒可以定義函數(shù)、調(diào)用函數(shù),復(fù)用函數(shù)号涯,這是函數(shù)的本職功能茅逮,也是函數(shù)的語法特性冯事。
  • 用法2:把函數(shù)作為數(shù)據(jù)/值使用
  • 用法3:把函數(shù)作為命名空間使用

把函數(shù)作為數(shù)據(jù)/值使用

函數(shù)也是數(shù)據(jù)/值。這意味著我們可以把函數(shù)賦值給變量德绿、賦值給對象屬性、賦值給數(shù)組元素退渗、賦值給形參等

示例: 函數(shù)名本質(zhì)上就是一個(gè)變量

function sum(a,b){return a + b}

把函數(shù)賦值給另一個(gè)變量

let s = sum
s(2,3)//5

把函數(shù)賦值給對象的屬性

let obj = {name:'張三',age:19}
obj.s = sum
obj.s(3,3)

把函數(shù)賦值給數(shù)組

let arr = [1,2,sum]
console.log(arr[2](arr[0], arr[1]));

把函數(shù)作為命名空間使用

當(dāng)把函數(shù)作為命名空間使用時(shí)移稳,可以確保函數(shù)體內(nèi)的變量不會污染全局命名空間。

有名函數(shù)

let maxValue = 100

 function max(a,...aaa) {//只定義了全局變量max
     let maxValue = -Infinity
     for (n of aaa) {
         if (n > maxValue) {
            maxValue = n
         }
     }
     return maxValue
}
console.log(window.max);//我不想添加到window上会油,可以使用自執(zhí)行函數(shù)

自執(zhí)行函數(shù)(推薦)

;(function(a,...aaa){
    let maxValue = -Infinity
    for (n of aaa) {
        if (n > maxValue) {
            maxValue = n
        }
    }
    console.log(maxValue);
    return maxValue
}(33,4,555))
// console.log(window.max)

====2. 作用域與變量提升 ====

變量作用域

復(fù)習(xí)
let 定義變量的關(guān)鍵字个粱,它是臨時(shí)性賦值。
const定義常量的關(guān)鍵字翻翩,它是永久性賦值都许。聲明常量約定全部使用大寫字母命名標(biāo)識符。
varES6之前定義變量的關(guān)鍵字嫂冻,它是臨時(shí)性賦值胶征。

變量作用域指定義變量的區(qū)域。 變量在哪個(gè)區(qū)域定義,就在哪個(gè)區(qū)域發(fā)生作用桨仿。變量作用域決定了變量的可訪問性睛低。在當(dāng)前定義區(qū)域內(nèi),變量可以被訪問到服傍,在這個(gè)區(qū)域以外钱雷,變量不能被訪問到。

示例:全局作用域 VS 局部作用域

<script>
  var a = 10 //變量a擁有全局作用域
  function fn(){
    console.log(a) //輸出10,變量a在全局任何位置都可以訪問
    var b = 20
    console.log(b) //輸出20吹零,變量b定義在函數(shù)fn內(nèi)罩抗,故擁有局部作用域,在函數(shù)fn內(nèi)可以訪問
  }
  console.log(b) // 報(bào)錯(cuò)瘪校。變量b是局部變量澄暮,無法從函數(shù)fn外面訪問。
</script>

有兩種類型的作用域

  • 全局作用域:局部作用域之外的區(qū)域就是全局作用域阱扬。
  • 局部作用域:局部作用域指函數(shù)作用域塊級作用域泣懊。這兩種局部作用域使用不同的關(guān)鍵詞定義:
    • 函數(shù)作用域:指在函數(shù)體內(nèi),使用關(guān)鍵詞var定義的變量麻惶,會創(chuàng)建變量的函數(shù)作用域馍刮,也就是說變量只能在當(dāng)前函數(shù)體內(nèi)才可以訪問。注:變量定義在if或for創(chuàng)建的代碼塊內(nèi)窃蹋,是不會創(chuàng)建函數(shù)作用域的卡啰。
    • 塊級作用域: 指在大括號包裹的區(qū)域內(nèi)静稻,使用關(guān)鍵詞letconst定義的變量,會創(chuàng)建塊級作用域匈辱,只能在大括號內(nèi)才可以訪問振湾。

示例:函數(shù)作用域

<script>
  var a = 10
  function fn(){
    var a = 20
    console.log(a) //20 這個(gè)a定義在函數(shù)內(nèi),是局部變量
  }
  console.log(a) //10 這個(gè)a定義在函數(shù)外亡脸,是全局變量
</script>

示例:塊級作用域

<script>
  let a = 10
  if(a === 10){
    let a = 20//let在這里創(chuàng)建了局部作用域押搪,故變量b是局部變量。
    var b = 30 //var只能創(chuàng)建函數(shù)作用域浅碾,無法創(chuàng)建塊級作用域大州。故在這里創(chuàng)建的變量b是全局變量
    console.log(a) //20 這個(gè)a定義在函數(shù)內(nèi),是局部變量
  }
  console.log(b) //10 因?yàn)閎定義在全局垂谢,故b可以讀取到10
  console.log(a) //10 這個(gè)a定義在函數(shù)外厦画,是全局變量
</script>

變量聲明提升

JavaScript 提升是指解釋器似乎在執(zhí)行代碼之前將函數(shù)、變量或類的聲明移動(dòng)到其作用域頂部的過程滥朱。
示例:var

console.log(x === undefined); // true
var x = 3;

(function() {
  console.log(x); // undefined
  var x = 'local value';
})();

等價(jià)于

var x;
console.log(x === undefined); // true
x = 3;

(function() {
  var x;
  console.log(x); // undefined
  x = 'local value';
})();

示例:let 與 const的臨時(shí)性死區(qū)
從塊開始到聲明被處理根暑,變量都處于“時(shí)間死區(qū)”

console.log(x); // ReferenceError
const x = 3;

console.log(y); // ReferenceError
let y = 3;

如果 const x = 2 聲明根本沒有提升,那么 console.log(x) 語句應(yīng)該能夠從上層作用域讀取 x 值焚虱。然而购裙,因?yàn)?const 聲明仍然“污染”了它定義的整個(gè)范圍,console.log(x) 語句改為從 const x = 2 聲明中讀取 x鹃栽,它尚未初始化躏率,并拋出 ReferenceError。
盡管如此民鼓,將詞法聲明描述為非提升可能更有用薇芝,因?yàn)閺墓髁x的角度來看,這些聲明的提升不會帶來任何有意義的特征丰嘉。

變量聲明提升是關(guān)于函數(shù)作用域的一個(gè)重要問題夯到。先看一個(gè)的例子:

//請問console.log()第一次輸出的是什么?
var n = 123
function fn(){
  console.log(n) //?
  var n = 456
  console.log(n)
}
fn()

您可能會想當(dāng)然第認(rèn)為第一次console.log()輸出的是123饮亏,也就是全局變量n的值耍贾。但事實(shí)并非如此,第一個(gè)console.log()實(shí)際上輸出的是undefined路幸。因?yàn)樵诤瘮?shù)體內(nèi):變量n也有定義荐开,故局部變量n會覆蓋全局變量n。盡管在函數(shù)體內(nèi)简肴,第一次調(diào)用局部變量n的時(shí)候晃听,n還沒有定義安岂,但n實(shí)際上已經(jīng)存在于本地空間(函數(shù)體內(nèi))了楔绞,這種特殊現(xiàn)象叫做提升(hoisting) 脂信。

提升(hoisting) :指當(dāng)JS執(zhí)行過程進(jìn)入新函數(shù)時(shí)齿坷,新函數(shù)內(nèi)的的所有變量聲明(如var n)都會被提升到當(dāng)前作用域的頂部。

示例:模擬var變量聲明提升

<script>
/**********************
var n  //變量聲明被提升至頂部
*********************/
console.log(n) // undefined(在這里可以讀取到n的原因就在于變量聲明提升)
var n = 123
function fn(){
    /*****變量聲明被提升至頂部******
    var n  
    *************************/
    console.log(n) //undefined(在這里可以讀取到n的原因就在于變量聲明提升)
    var n = 456
    console.log(n) //456
}
fn()
</script>

示例: 模擬函數(shù)提升

/********整個(gè)函數(shù)被提升到頂部**********
function fn(){
  console.log('hello world')
}           
*******************************/
fn() // 'hello world' (在這里可以讀取到fn()的原因就在于函數(shù)提升)
function fn(){
  console.log('hello world')
}

函數(shù)聲明也會創(chuàng)建變量初斑,所以函數(shù)聲明也會發(fā)生變量提升辛润,與變量聲明提升不同的是,整個(gè)函數(shù)见秤,包括函數(shù)聲明與函數(shù)體都會被提升至當(dāng)前作用域頂部频蛔。

做題思路

  1. 要知道只有一個(gè)全局作用域。
  2. 你只需確定局部作用域有幾個(gè)秦叛;(局部作用域有兩種:var聲明會創(chuàng)建函數(shù)作用域,let和const聲明會塊級作用域瀑粥。)
  3. 預(yù)解析:在每個(gè)作用域內(nèi)做預(yù)解析挣跋;(var afunction(){}一定會提升,letconst提升會報(bào)錯(cuò)狞换,所以你就理解為let和const不提升)
  4. 逐行解析: 逐行讀取代碼
  5. 優(yōu)先級:①如果出現(xiàn)變量名和函數(shù)名相同的情況避咆,那么函數(shù)a的優(yōu)先級高于變量a的優(yōu)先級;②如果局部變量和全局變量同名修噪,那么局部變量覆蓋全局變量查库。

示例



示例


====3. 閉包 ====

閉包

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市黄琼,隨后出現(xiàn)的幾起案子樊销,更是在濱河造成了極大的恐慌,老刑警劉巖脏款,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件围苫,死亡現(xiàn)場離奇詭異,居然都是意外死亡撤师,警方通過查閱死者的電腦和手機(jī)剂府,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來剃盾,“玉大人腺占,你說我怎么就攤上這事⊙髑矗” “怎么了衰伯?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長闰歪。 經(jīng)常有香客問我嚎研,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任临扮,我火速辦了婚禮论矾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘杆勇。我一直安慰自己贪壳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布蚜退。 她就那樣靜靜地躺著闰靴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪钻注。 梳的紋絲不亂的頭發(fā)上蚂且,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天,我揣著相機(jī)與錄音幅恋,去河邊找鬼杏死。 笑死,一個(gè)胖子當(dāng)著我的面吹牛捆交,可吹牛的內(nèi)容都是我干的淑翼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼品追,長吁一口氣:“原來是場噩夢啊……” “哼玄括!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起肉瓦,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤遭京,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后风宁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體洁墙,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年戒财,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了热监。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,488評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡饮寞,死狀恐怖孝扛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情幽崩,我是刑警寧澤苦始,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站慌申,受9級特大地震影響陌选,放射性物質(zhì)發(fā)生泄漏理郑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一咨油、第九天 我趴在偏房一處隱蔽的房頂上張望您炉。 院中可真熱鬧,春花似錦役电、人聲如沸赚爵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冀膝。三九已至,卻和暖如春霎挟,著一層夾襖步出監(jiān)牢的瞬間窝剖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工酥夭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留枯芬,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓采郎,卻偏偏與公主長得像,于是被迫代替她去往敵國和親狂魔。 傳聞我的和親對象是個(gè)殘疾皇子蒜埋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評論 2 359

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