javascript使用原型鏈來解析屬性值(很類似於使用做用域鏈來解析變量)javascript
原型鏈是往"內部"找java
做用域鏈是往「外部」找閉包
使用Object.create()和工廠函數 取代 new(雖然如今new用的最多,大多數庫源代碼都是用new的方式來建立對象的,但畢竟javascirpt是原型繼承,因此隱藏oop的new)函數
Object.create僅支持ie9+,oop
因此要作兼容性判斷this
var objectCreate = function(arg) { if(!arg) { return {};} function obj(){}; obj.prototype = arg; return new obj; } Object.create = Object.create || objectCreate ;//這是一種很經常使用的修復兼容性和檢測庫是否重複加載的方式
執行環境是函數被調用執行時才創建的,而做用域是根據代碼結構來定去區分的,無論函數賦值到哪去,(能夠大概認爲定義函數時函數就在內存中的一段地址,變量都是引用,沒法改變其地址,因此做用域都是同樣的)prototype
但執行環境一個特有的變量就是this,this是根據執行環境要肯定它是指向那個對象。對象
執行環境執行過程大體分爲兩輪,blog
1:聲明參數並賦值繼承
2:聲明局部變量但不賦值
3:聲明函數而且賦值,但不執行(其優先級大於2)
//其中也有一點,函數也是對象,因此函數的某些定義對象也因此,例如做用域,準確來講我認爲做用域是按對象來劃分的
var me = (function() { var name = "jack", jjLength = 18; return { yetName: function() { console.log(name); }, yetJJ : function() { console.log(jjLength); } } })(); me.yetName();//jack
做爲匿名自執行函數,執行完一次以後便結束,
裏面的變量就永遠都不會更新,除非你定義了set方法
還有一點很關鍵,函數和對象的賦值都是引用賦值,二基礎變量是值傳遞。(也能夠這樣說,複雜數據類型是引用傳遞,基礎數據類型是值傳遞)
這裏代碼能夠解釋:
var a = { bb : '3', cc : function() { console.log(this.bb); } } a.cc();//3 var b = a; var bbb = a.bb; b.bb = '2333'; a.cc();//2333 console.log(bbb);//3
就我而言看了不少書,當講起閉包的概念的時候,沒幾本書能完全的解釋,例如」閉包是讓內部函數能訪問外部函數的變量的特性仍是xxxxbalabala「,反正都不懂
但我曾看到一個最好的解釋是:
閉包是阻止javascirpt垃圾回收器將變量從內存中移除的方法,使得在建立變量的執行環境的外面能訪問到該變量。(雖然我一直吐槽爲什麼叫作「閉包」,暫時還不懂命名的意義)
話說閉包是如何工做的呢?答案就在執行環境對象中。//因此是執行時生成的,關於javascirpt垃圾回收規則,當變量被引用時邊不會被回收
閉包實現柯里化,如下是seajs源碼中的一段
function isType(type) { return function(obj) { return {}.toString.call(obj) == "[object " + type + "]" } } var isObject = isType("Object") var isString = isType("String") var isArray = Array.isArray || isType("Array") var isFunction = isType("Function")
閉包可能會致使內存使用失控(思考一下內存泄露)
由於若是一個函數一直循環執行,便每次建立一個執行環境,內存沒法獲得釋放,因此便會形成內存使用失控