本文主要講解、理清一些函數經常使用的知識點:遞歸、閉包是什麼、閉包使用場景、什麼是原型和原型鏈、如何實現繼承、繼承的原理,原文。javascript
函數的遞歸就是在函數中調用自身html
舉一個實例,著名斐波那契數列如何求得,問題是這樣的:java
定義出來的數列是git
咱們須要求得 n 月有多少對兔子,經過遞歸算法能夠求得github
function fn(n) { return n < 2 ? 1 : fn(n - 1) + fn(n - 2) } var count = fn(30); console.log(count);
什麼是閉包?閉包就是函數,它能夠繼承並訪問自身所被聲明的函數做用域內的變量。算法
function fn1 () { var a = 'hello' function fn2 () { console.log(a) } } fn1() // 其中 fn2 就是閉包函數
閉包有不少使用場景,如下舉例:閉包
function Person(){ var name = "default"; return { getName : function(){ return name; }, setName : function(newName){ name = newName; } } }; var person = Person() console.log(person.getName()) // default person.setName('xiaomuchen') console.log(person.getName()) // xiaomuchen var person2 = Person() console.log(person2.getName()) // default
上述函數,使用閉包建立私有變量 name,變量不可被外部直接操做、獲取,只能經過返回的接口控制。函數
好比在開發頁面時,須要在頁面初始化時,你須要當即作一些操做,那麼能夠在頁面中使用匿名自執行函數
,它會在 JS 引擎讀取到這部分代碼時就當即執行。this
// 在 title 上添加頁面打開時間 (function(){ var openTime = new Date() document.title = document.title + openTime })();
先問一個問題:__proto__ 和 prototype 會出如今什麼地方?它們之間是什麼關係?實現繼承依賴什麼?spa
1.JavaScript 中每個對象都擁有原型鏈(__proto__)指向其構造函數的原型(prototype)
var a = {} a.__proto__ === Object.prototype // true function Person () {} Person.__proto__ === Function.prototype // true var p = new Person() p.__proto__ === Person.prototype // true
2.JavaScript 中每個函數都擁有原型(prototype),原型也是一個對象,這個對象包括:原型鏈、原型方法(屬性)、函數構造,同理它的原型鏈指向其構造函數的原型
function Person () {} Person.prototype.getName = function () {} Object.getOwnPropertyNames(Person.prototype) // ["constructor", "getName"] Person.prototype.__proto__ === Object.prototype // true
3.當訪問一個函數上的屬性時,先嚐試訪問自身上的屬性,再嘗試訪問其原型上的屬性
。當訪問一個對象上的屬性時,先嚐試訪問自身上的屬性,再經過原型鏈嘗試訪問其構造函數原型上的屬性
。若是沒有則經過原型上的原型鏈,繼續向上查找,直到訪問 Object.prototype 上的屬性,若是仍是沒有,由於 Object.prototype 是一個沒有 __proto__ 的對象,則查詢到此爲止,返回 undefined。
function Person () {} Person.getName = function () { console.log('Person1') } Person.prototype.getName = function () { console.log('Person2') } var p = new Person() Person.getName() // Person1 p.getName() // Person2 console.log(typeof p.getClass) // undefined
JavaScript 函數經過原型和原型鏈實現繼承
function superA (name) { this.name = name } superA.prototype.getName = function () { console.log(this.name) } function subA (name) { superA.call(this, name) // 繼承屬性 } subA.prototype = new superA() // 繼承方法 var a1 = new subA('xiaomuchen') a1.getName() // xiaomuchen
上述代碼,描述了一個函數的經典繼承,其工做原理是這樣的:
本文歸納了遞歸、閉包、原型、繼承,理清這些基本的概念,有助於你接納更多的東西,咱們會在下一個章節對函數進行更深刻的討論。
做者:肖沐宸,github。