閉包
定義:能夠訪問另一個函數作用域的變量的函數。
作用:可以通過閉包,設計私有變量及方法
實例:
function outer() { var a = '變量1' var inner = function () { console.info(a) } return inner // inner 就是一個閉包函數,因為他能夠訪問到outer函數的作用域 } var inner = outer() // 獲得inner閉包函數 inner() //"變量1"
模擬實現c#或java中創建類的功能
(function() { var name = "wangyu" Person = function (val) { name = val } Person.prototype.setName = function (val) { name = val } Person.prototype.getName = function () { return name } }) var person1 = new Person('sj') console.log(this.name) // 輸出 undefined, 因為在function作用域外不能訪問 console.log(person1.getName()) // 輸出sj
容易產生的問題:
1. 引用的var定義變量可能發生變化,es6中使用let將不會有此問題
2. this的指向問題
var object = { name: ''object", getName: function() { return function() { console.info(this.name) } } } object.getName()() // underfined
// 因為里面的閉包函數是在window作用域下執行的,也就是說,this指向windows
3. 內存泄漏問題
function showId() { var el = document.getElementById("app") el.onclick = function(){ aler(el.id) // 這樣會導致閉包引用外層的el,當執行完showId后,el無法釋放 } } // 改成下面 function showId() { var el = document.getElementById("app") var id = el.id el.onclick = function(){ aler(id) // 這樣會導致閉包引用外層的el,當執行完showId后,el無法釋放 } el = null // 主動釋放el }
原型鏈(簡書:https://www.jianshu.com/p/08c07a953fa0)
定義:每個對象都可以有一個 原型 _proto_,這個原型可以有他自己的原型,以此類推,形成一個原型鏈;
原型指針:
_prototype_:prototype屬性是函數所獨有的,是從一個函數指向一個對象。它的含義是函數的原型對象(也就是這個函數所創建[new]實例的原型對象);這個屬性是一個指針,指向一個對象,這個對象的用途就是包含所有實例共享的屬性和方法(我們把這個對象叫做原型對象);
_proto_:_proto_是對象獨有的,他總是指向 prototype(也就是指向構造函數的原型對象);函數也會有這個屬性(因為再js的宇宙里萬物皆對象,包括函數),指向null
constructor:每個函數都有一個原型對象,該原型對象有一個constructor屬性,指向創建對象的函數本身。
結論:
1. _proto_ 是原型鏈查詢中實際使用到的,它總是指向prototype
2. prototype是函數所獨有的,在定義構造函數時自動創建,他總是被 _proto_ 所指
所有的對象都有 _proto_ 屬性,函數這個特殊對象除了具有_proto_屬性,還有特有的原型屬性 prototype。prototype對象有 _proto_ 和 construction 屬性。prototype可以給函數和對象添加可共享(繼承)的方法、屬性, _proto_是查找某函數或對象的原型鏈的方式。construction包含一個指針,指向原構造函數
原型鏈對象實例圖:

沒有退路的時候,正是潛力發揮最大的時候。
