JavaScript入門——函數(shù)(三)

函數(shù)是對象金抡,函數(shù)可以存放在變量中举农,作為參數(shù)傳遞荆针。函數(shù)可以返回函數(shù)。因為函數(shù)也是對象颁糟,因此函數(shù)可以擁有方法航背。

定義

ES6 之前的函數(shù)定義可以通過函數(shù)表達(dá)式或函數(shù)語句,分別是:

var test = function() {}

function test2() {}

函數(shù)語句在解析時會被提升:不管函數(shù)語句放置在哪里棱貌,它會被移動到所在作用域的頂部玖媚。可使得函數(shù)不必先聲明后使用婚脱。

ES6 新增了箭頭函數(shù):

let odds = evens.map(v => v + 1)

=> 之前是函數(shù)參數(shù)列表今魔。如果只有一個參數(shù)可以省略括號。如果沒有參數(shù)障贸,必須加空的括號错森。多個參數(shù)也必須使用括號。

let test1 = v => v + 1
let test1 = () => console.log("hello")
let test1 = (a, b) => a + b

箭頭后如果只有一個語句可以省略大括號篮洁,且如果是語句則語句的值作為函數(shù)返回值涩维,即可以省略 return。如果有多個語句袁波,必須使用大括號瓦阐,且返回值一定要顯式通過 return 返回蜗侈。

let test1 = v => v + 1 // 函數(shù)返回 v + 1,不需要 return
let test2 = v => {
    let a = v + 1
    return a
}

調(diào)用

除了聲明時定義的形式參數(shù)睡蟋,每個函數(shù)還接收兩個附加參數(shù):thisarguments宛篇。

當(dāng)實參與形參個數(shù)不匹配時不會導(dǎo)致運行時錯誤。如果實參過多薄湿,多出的參數(shù)被忽略叫倍。如果參數(shù)值過少,缺失的值將被替換為 undefined豺瘤。對參數(shù)值不會進(jìn)行類型檢查吆倦。

函數(shù)內(nèi)的 this

函數(shù)內(nèi)可以訪問一個隱式的變量 this,它的值取決于函數(shù)定義和調(diào)用的方式坐求。

如果函數(shù)不是通過箭頭定義的蚕泽,this 的值完全取決于調(diào)用方式。有四種:函數(shù)式桥嗤、方法式须妻、構(gòu)造式、apply泛领。

函數(shù)跟方法的區(qū)別即直接調(diào)用還是通過一個對象調(diào)用荒吏。當(dāng)函數(shù)被存儲為對象的一個屬性時,稱其為方法渊鞋。當(dāng)方法被調(diào)用時绰更,this 綁定到那個對象。

函數(shù)調(diào)用時锡宋,this 被綁定到全局對象儡湾。

let obj = {
    a: 1,
    good: function() { console.log(this && this.a) }
}
obj.good() // 方法,打印 1

let g = obj.good
g() // 函數(shù)执俩,打印 undefined

構(gòu)造式即通過 new 調(diào)用徐钠,此時函數(shù)是構(gòu)造器,this 指要創(chuàng)建的對象役首。

function Apple {
    this.red = true
}
let apple = new Apple()

applycall 函數(shù)的兩個特殊方法尝丐,可以顯式指定 this 的值。二者的區(qū)別是宋税,apply 需要實參放在一個數(shù)組中傳遞摊崭,而 call 的實參直接列出,見例子:

let obj = {
    add: function(c, d) { this.a + this.b + this.c + this.d }
}

let add = obj.add
add.apply({a: 1, b: 2}, [3, 4])
add.call({a: 1, b: 2}, 3, 4)

ES5 有一個 bind 方法可以強(qiáng)制綁定函數(shù)的 this 到某個對象杰赛。此時呢簸,函數(shù)的調(diào)用不在受調(diào)用方式的影響。

let obj = {
    a: 1,
    b: 2,
    add: function() { this.a + this.b }
}

let add = obj.add
add() // 報錯!

add = add.bind(obj)
add() // 正常

如果函數(shù)通過箭頭定義根时,則 this 綁定到函數(shù)定義時的上下文瘦赫。

var bob = {
    _name: "Bob",
    _friends: [],
    printFriends() {
        this._friends.forEach(f =>
            console.log(this._name + " knows " + f))
    }
}

某些情況下,如果必須訪問一個因為某種原因訪問不到的 this蛤迎,一般先將這個 this 賦給另外一個變量(一般命名為 that)确虱。然后傳遞或通過閉包訪問這個變量。

myObject.double = function () {
    var that = this
    var helper = function () {
        that.value = add(that.value, that.value)
    }
    helper()
}

默認(rèn)參數(shù)(ES6)

function myfunction(value, option = 'default') {
}

myfunction(1)
myfunction(1, "my")

剩余參數(shù)和展開參數(shù)(ES6)

利用 ...替裆,調(diào)用函數(shù)時校辩,將一個數(shù)組展開為多個參數(shù)。反過來辆童,收集剩余參數(shù)到一個數(shù)組宜咒。此特性用于替代 arguments

function f(x, ...y) {
    // y is an Array
    return x * y.length
}

f(3, "hello", true) === 6

function f(x, y, z) {
    return x + y + z
}
f(...[1,2,3]) === 6

arguments

通過 arguments 數(shù)組可以訪問所有實參把鉴,包括那些多余參數(shù)故黑。這使得編寫一個無需指定參數(shù)個數(shù)的函數(shù)成為可能:

var sum = function () {
    var i, sum = 0
    for (i = 0; i < arguments.length; i += 1) {
        sum += arguments[i]
    }
    return sum
};

document.writeln(sum(4, 8, 15, 16, 23, 42)) // 108

因為語言的設(shè)計錯誤,arguments 并不是一個真正的數(shù)組庭砍。它只是一個“類似數(shù)組”的對象场晶。argumentslength 屬性,但缺少所有的數(shù)組方法怠缸。

返回

函數(shù)總是會返回一個值诗轻。如果沒有指定返回值,返回 undefined凯旭。

閉包

函數(shù)定義可以嵌套概耻。內(nèi)部函數(shù)可以訪問到外圍函數(shù)的參數(shù)和變量thisarguments 除外)。通過函數(shù)字面量創(chuàng)建的函數(shù)對象包含到外部上下文的連接罐呼,這被稱為閉包

通過閉包可以實現(xiàn)私有字段侦高、方法和公有字段嫉柴、方法的分隔。例如下面代碼奉呛,參數(shù) status 是私有的计螺,只能通過 getStatus 方法獲取:

var quo = function (status) {
    return {
        getStatus: function () {
            return status
        }
    }
}
// Make an instance of quo.
var myQuo = quo("amazed")
document.writeln(myQuo.getStatus())

這個 que 函數(shù)被設(shè)計成無須在前面加上 new 來使用瞧壮,所以名字也沒有首字母大寫登馒。當(dāng)調(diào)用 que 時,返回一個新對象咆槽。該對象包含一個 getStatus 方法陈轿。即使 que 已經(jīng)返回了,但 getStatus 方法仍能訪問 que 對象的 status 參數(shù)。getStatus 方法并不訪問該參數(shù)的一個拷貝麦射,它訪問的是該參數(shù)本身蛾娶。函數(shù)可以訪問被創(chuàng)建時所處的上下文環(huán)境,這被稱為閉包潜秋。

理解內(nèi)部函數(shù)訪問外部函數(shù)的變量的實際值而非副本是很重要的蛔琅,見下面這個錯誤:

var add_the_handlers = function (nodes) {
    var i
    for (i = 0; i < nodes.length; i += 1) {
        nodes[i].onclick = function (e) {
            alert(i)
        }
    }
}

原本想每次彈出時顯示節(jié)點序號,但最后每個節(jié)點顯示的都是數(shù)字都等于節(jié)點數(shù)組峻呛。原因是事件處理函數(shù)綁定的是變量 i罗售,而非 i 當(dāng)時的值。

正確的修改钩述,利用傳遞參數(shù)綁定當(dāng)時的值:

var add_the_handlers = function (nodes) {
    var i
    for (i = 0; i < nodes.length; i += 1) {
        nodes[i].onclick = function (i) {
            return function (e) {
                alert(i)
            }
        }(i)
    }
}

ES6 的 let 也可以解決該問題寨躁。每個 i 定義在自己的作用域中,是獨立的切距。

var add_the_handlers = function (nodes) {
    for (let i = 0; i < nodes.length; i += 1) {
        nodes[i].onclick = function (e) {
            alert(i)
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末朽缎,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子谜悟,更是在濱河造成了極大的恐慌话肖,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件葡幸,死亡現(xiàn)場離奇詭異最筒,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蔚叨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門床蜘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蔑水,你說我怎么就攤上這事邢锯。” “怎么了搀别?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵丹擎,是天一觀的道長。 經(jīng)常有香客問我歇父,道長蒂培,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任榜苫,我火速辦了婚禮护戳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘垂睬。我一直安慰自己媳荒,他們只是感情好抗悍,可當(dāng)我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著肺樟,像睡著了一般檐春。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上么伯,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天疟暖,我揣著相機(jī)與錄音,去河邊找鬼田柔。 笑死俐巴,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的硬爆。 我是一名探鬼主播欣舵,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼缀磕!你這毒婦竟也來了缘圈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤袜蚕,失蹤者是張志新(化名)和其女友劉穎糟把,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體牲剃,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡遣疯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了凿傅。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缠犀。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖聪舒,靈堂內(nèi)的尸體忽然破棺而出辨液,到底是詐尸還是另有隱情,我是刑警寧澤箱残,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布室梅,位于F島的核電站,受9級特大地震影響疚宇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜赏殃,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一敷待、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧仁热,春花似錦榜揖、人聲如沸勾哩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽思劳。三九已至,卻和暖如春妨猩,著一層夾襖步出監(jiān)牢的瞬間潜叛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工壶硅, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留威兜,地道東北人。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓庐椒,卻偏偏與公主長得像椒舵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子约谈,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,627評論 2 350

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

  • 函數(shù)和對象 1笔宿、函數(shù) 1.1 函數(shù)概述 函數(shù)對于任何一門語言來說都是核心的概念。通過函數(shù)可以封裝任意多條語句棱诱,而且...
    道無虛閱讀 4,550評論 0 5
  • 第5章 引用類型(返回首頁) 本章內(nèi)容 使用對象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,219評論 0 4
  • ??引用類型的值(對象)是引用類型的一個實例军俊。 ??在 ECMAscript 中侥加,引用類型是一種數(shù)據(jù)結(jié)構(gòu),用于將數(shù)...
    霜天曉閱讀 1,044評論 0 1
  • 第3章 基本概念 3.1 語法 3.2 關(guān)鍵字和保留字 3.3 變量 3.4 數(shù)據(jù)類型 5種簡單數(shù)據(jù)類型:Unde...
    RickCole閱讀 5,106評論 0 21
  • 出現(xiàn)原因:一些文件或者符號重復(fù)了 案例一:在工程中重復(fù)導(dǎo)入了某一個類或文件粪躬,這一般出現(xiàn)在你添加第三方庫的時候比較多...
    踐行者_(dá)Leng閱讀 234評論 0 0