摘要:函數(shù)表達(dá)式和閉包函數(shù)聲明的一個(gè)重要特征是函數(shù)聲明提升如遞歸遞歸函數(shù)是在一個(gè)函數(shù)通過(guò)名字調(diào)用自身的情況下構(gòu)成的。注意中已經(jīng)是塊級(jí)作用域了,所以這些東西感覺(jué)實(shí)際用途沒(méi)有那么大,但是對(duì)理解閉包對(duì)作用域鏈中的屬性的引用,這一點(diǎn)還是有作用的。
函數(shù)表達(dá)式和閉包 1. 函數(shù)聲明的一個(gè)重要特征是函數(shù)聲明提升
如:
sayHi() function sayHi () { console.log("hi") }2. 遞歸
遞歸函數(shù)是在一個(gè)函數(shù)通過(guò)名字調(diào)用自身的情況下構(gòu)成的。
如:
function factorial (num) { if (num <= 1) { return 1 } else { return num * factorial(num - 1) // 這里存在強(qiáng)耦合,不太好 } }
比如下面的代碼會(huì)導(dǎo)致它出錯(cuò)
var anotherFactorial = factorial factorial = null anotherFactorial(3) // 出錯(cuò):factorial is not a function arguments.callee 是一個(gè)指向正在執(zhí)行函數(shù)的指針,可以做如下改善: function factorial (num) { if (num <= 1) { return 1 } else { return num * arguments.callee(num - 1) } }
嚴(yán)格模式下使用 arguments.callee 會(huì)出錯(cuò)。可以做以下改善
var factorial = (function f (num) { if (num <= 1) { return 1 } else { return num * f(num - 1) } })
我的理解:這里的 f 只在函數(shù)內(nèi)部有效,所以不會(huì)受到外界影響,外部得不到這個(gè)變量。
(function test () { console.log("this is test") }) test() // 報(bào)錯(cuò)。
用小括號(hào)括起來(lái)的函數(shù)聲明在外部是得不到的,test()只有函數(shù)內(nèi)部可以用
3. 閉包閉包指有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域中的變量的函數(shù)。
創(chuàng)建閉包的常用方式,就是在一個(gè)函數(shù)內(nèi)部創(chuàng)建另一個(gè)函數(shù)。
如:
function createComparisonFunction (propertyName) { return function(obj1, obj2) { var value1 = obj1[propertyName] var value2 = obj2[propertyName] return value1 - value2 } } var obj = [{age: 13}, {age: 29}, {age: 18}, {age: 37}, {age: 5}, {age: 14}] var compare = createComparisonFunction("age") var obj2 = obj.sort(function (a, b) { compare(a, b) })
這個(gè)例子中,內(nèi)部函數(shù)訪問(wèn)了外部函數(shù)的變量 propertyName,而且即使被返回了在其它地方調(diào)用,仍然可以訪問(wèn)。
是因?yàn)閮?nèi)部函數(shù)的作用域鏈中包含了 createComparisonFunction 的作用域鏈。
由于閉包會(huì)攜帶包含它的函數(shù)的作用域,因此會(huì)比其它函數(shù)占用更多的內(nèi)存。
4. 閉包與變量閉包作用域鏈的配置機(jī)制有一個(gè)副作用,閉包只能取得包含函數(shù)中任何變量的最后一個(gè)值,因?yàn)殚]包保存的是整個(gè)變量對(duì)象,不是某個(gè)特殊的變量。
如:
function createFunction () { var result = [] for (var i = 0; i < 10; i++) { result[i] = function () { return i } } return result } // 返回?cái)?shù)組中每個(gè)函數(shù)的執(zhí)行結(jié)果都是10
改善版:
function createFunction () { var result = [] for (var i = 0; i < 10; i++) { result[i] = (function (num) { return function () { return num } }(i)) } return result }
這樣就按預(yù)期來(lái)返回值了,這里通過(guò)立即執(zhí)行函數(shù)把變量 i 的當(dāng)前值作為參數(shù)傳遞到了內(nèi)部閉包函數(shù)里,由于函數(shù)的基本類型參數(shù)是按值傳遞,
所以每個(gè)內(nèi)部閉包函數(shù)保存的值都是當(dāng)前 i 值。
var name = "window"; (function () { this.name = "fn" console.log(this.name) // "fn" var obj = { name: "obj", getFunc: function () { return function () { console.log(this.name) } } } obj.getFunc()() // "fn" }())
閉包函數(shù)的this指向它被調(diào)用時(shí)的作用域?qū)ο蟆?br>每個(gè)函數(shù)被調(diào)用時(shí)都會(huì)自動(dòng)取得兩個(gè)特殊的變量:this 和 arguments。在調(diào)用這兩個(gè)變量時(shí),只會(huì)搜索到其活動(dòng)對(duì)象為止。
this 的改變,如:
var name = "the Window" var obj = { name: "obj", getName: function () { console.log(this.name) } } obj.getName(); // "obj" (obj.getName)(); // "obj" (obj.getName = obj.getName)(); // "the Window" var obj2 = { name: "obj2" } (obj2.getName = obj.getName)(); // "the Window" // 這里我的理解是相當(dāng)于一個(gè)立即執(zhí)行函數(shù),這個(gè)立即執(zhí)行函數(shù)是在window環(huán)境下被執(zhí)行的,所以返回window下的變量值。 obj2.getName = obj.getName obj2.getName() // "obj2"6. 通過(guò)構(gòu)造函數(shù)創(chuàng)建私有變量和特權(quán)方法
如:
function Person (name) { this.getName = function () { return name } this.setName = function (value) { name = value } } var ming = new Person("ming") ming.name // undefined ming.getName() // "ming" ming.setName("ming2") ming.getName() // "ming2"
說(shuō)明:getName() setName() 在構(gòu)造函數(shù)外部使用,只有這兩個(gè)方法有權(quán)訪問(wèn)私有變量name,沒(méi)有其它辦法,因?yàn)樗鼈冏鳛殚]包能夠通過(guò)作用域鏈訪問(wèn)name
這種方法創(chuàng)建私有變量和特權(quán)方法有構(gòu)造函數(shù)所共有的缺點(diǎn)——函數(shù)沒(méi)有復(fù)用。
(function () { var name = "" Person = function (value) { name = value } Person.prototype.getName = function () { return name } Person.prototype.setName = function (value) { name = value } }()) var ming = new Person("ming") ming.getName() // "ming" ming.setName("ming2") ming.getName() // "ming2" var li = new Person("li") li.getName() // "li" ming.getName() // "li" // 說(shuō)明所有實(shí)例都是對(duì)作用域鏈中的 name 的引用
說(shuō)明:這里立即執(zhí)行函數(shù)里Person使用函數(shù)表達(dá)式來(lái)定義,而且沒(méi)有使用 var , 是為了形成全局變量。
或者先在全局定義一下 Person也可以。 var Person = function () {}
注意:es6 中已經(jīng)是塊級(jí)作用域了,所以這些東西感覺(jué)實(shí)際用途沒(méi)有那么大,但是對(duì)理解閉包對(duì)作用域鏈中的屬性的引用,這一點(diǎn)還是有作用的。
8. 模塊模式指為單例創(chuàng)建私有變量和特權(quán)方法。所謂單例,指的是只有一個(gè)實(shí)例的對(duì)象。
如:
var application = function () { var components = [] components.push(new BaseComponent()) // BaseComponent 指初始化組建 return { getComponentCount: function () { return components.length }, registerComponent: function (component) { if (typeof component === "object") { components.push(component) } } } }()
增強(qiáng)版,適合那種單例必須是某種類型的實(shí)例:
var application = function () { var components = [] components.push(new BaseComponent()) var app = new Base() app.getComponentCount = function () { return components.length } app.registerComponent = function (component) { if (typeof component === "object") { components.push(component) } } return app }()
// 函數(shù)表達(dá)式和閉包部分結(jié)束
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/86521.html
摘要:說(shuō)明此摘要筆記系列是我最近看高級(jí)程序設(shè)計(jì)第版隨手所記。摘要筆記本身沒(méi)有系統(tǒng)性,沒(méi)有全面性可言,寫(xiě)在這里供有一定基礎(chǔ)的前端開(kāi)發(fā)者參考交流。對(duì)每一項(xiàng)運(yùn)行給定函數(shù),返回該函數(shù)會(huì)返回的項(xiàng)組成的數(shù)組。是的反操作是的反操作第一部分結(jié)束。 說(shuō)明: 此摘要筆記系列是我最近看《JavaScript高級(jí)程序設(shè)計(jì)(第3版)》隨手所記。 里面分條列舉了一些我認(rèn)為重要的、需要記下的、對(duì)我有幫助的點(diǎn),是按照我看...
摘要:如果重設(shè)構(gòu)造函數(shù)的原型對(duì)象,那么,會(huì)切斷新的原型對(duì)象和任何之前已經(jīng)存在的構(gòu)造函數(shù)實(shí)例之間的聯(lián)系,它們引用的仍然是最初的原型。說(shuō)明返回的對(duì)象與構(gòu)造函數(shù)或者與構(gòu)造函數(shù)的原型屬性沒(méi)有關(guān)系。 說(shuō)明: 此摘要筆記系列是我最近看《JavaScript高級(jí)程序設(shè)計(jì)(第3版)》隨手所記。里面分條列舉了一些我認(rèn)為重要的、需要記下的、對(duì)我有幫助的點(diǎn),是按照我看的順序來(lái)的。摘要筆記本身沒(méi)有系統(tǒng)性,沒(méi)有全面性...
摘要:說(shuō)明此摘要筆記系列是我最近看高級(jí)程序設(shè)計(jì)第版隨手所記。其中,描述符對(duì)象的屬性必須是設(shè)置其中一個(gè)或多個(gè)值,可以修改對(duì)應(yīng)的特性值。如支持的瀏覽器,可以取得指定屬性的描述符。 說(shuō)明: 此摘要筆記系列是我最近看《JavaScript高級(jí)程序設(shè)計(jì)(第3版)》隨手所記。里面分條列舉了一些我認(rèn)為重要的、需要記下的、對(duì)我有幫助的點(diǎn),是按照我看的順序來(lái)的。摘要筆記本身沒(méi)有系統(tǒng)性,沒(méi)有全面性可言,寫(xiě)在這里...
摘要:關(guān)于對(duì)象定義了全局對(duì)象。支持的瀏覽器有除了接受要序列化的對(duì)象外,還可以接受另外兩個(gè)參數(shù)。如果是數(shù)值,則表示每個(gè)級(jí)別縮進(jìn)的空格數(shù),最大,超過(guò)的值自動(dòng)轉(zhuǎn)換成。字符串長(zhǎng)度超過(guò),結(jié)果中將只出現(xiàn)前個(gè)字符。會(huì)在結(jié)果字符串中插入換行符提高可讀性。 關(guān)于JSON 1. JSON 對(duì)象 es5 定義了全局對(duì)象 JSON。支持的瀏覽器有 IE8+ 、Firefox 3.5+ 、Safari 4+、Chro...
摘要:思路是,使用原型鏈對(duì)原型屬性和方法進(jìn)行繼承,借用構(gòu)造函數(shù)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承。注意使用寄生式繼承來(lái)為對(duì)象添加函數(shù),會(huì)由于不能做到函數(shù)復(fù)用而降低效率,這一點(diǎn)與構(gòu)造函數(shù)模式類似。無(wú)論什么情況下都會(huì)調(diào)用兩次超類型的構(gòu)造函數(shù)。 說(shuō)明: 此摘要筆記系列是我最近看《JavaScript高級(jí)程序設(shè)計(jì)(第3版)》隨手所記。里面分條列舉了一些我認(rèn)為重要的、需要記下的、對(duì)我有幫助的點(diǎn),是按照我看的順序來(lái)的...
閱讀 3696·2021-08-10 09:42
閱讀 591·2019-08-30 15:55
閱讀 890·2019-08-30 15:54
閱讀 3114·2019-08-30 13:45
閱讀 556·2019-08-29 16:23
閱讀 1992·2019-08-29 16:23
閱讀 986·2019-08-29 15:18
閱讀 2264·2019-08-29 12:57