本文您將看到如下內容:數組
一句話說明什麼是原型:原型就是一個JavaScript對象,原型能存儲咱們的方法,構造函數建立出來的實例對象可以引用原型中的方法。瀏覽器
有以下代碼服務器
function Foo(){ this.sayHello = function(){ } }
因爲對象是調用new Foo()
所建立出來的,所以每個對象在建立的時候,函數 sayHello 都會唄建立一次閉包
那麼有沒一個對象都含有一個獨立的,不一樣的,可是功能邏輯同樣的函數,好比:{} == {}
。框架
在代碼中方法就會消耗性能,最典型的資源就越是內存函數
這裏最好的方法就是將函數放在構造函數以外,那麼在構造函數中引用該函數便可性能
function sayHello () {} function Foo () { this.say = sayHello; }
會在開發中變得困難:引入框架危險,代碼繁冗很差維護。解決方法就是若是外面的函數不佔用其名字,並且在函數名下。this
每個函數在定義的時候,有一個神祕對象(就是原型對象,暫且這麼稱呼)被建立出來。spa
每個由構造函數建立的對象都會默認的鏈接到該神祕對象上。prototype
var f1 = new Foo(); var f2 = new Foo(); f1.sayHello(); //若是f1沒有sayHello那麼就會在Foo.prototype中去找
由構造函數建立出來的衆多對象共享一個對象就是:構造函數.prototype
只須要將共享的東西,重複會多佔用內存的東西放到構造函數.prototype
中,那麼全部的對象就能夠共享了。
function Foo(){} Foo.prototype.sayHello = function(){ console.log("…."); } var f1 = new Foo(); f1.sayHello(); var f2 = new Foo(); f2.sayHello(); console.log(f1.sayHello === f2.sayHello); // true
類class:在JS中就是構造函數
實例(instance)與對象(object)
鍵值對與屬性和方法
父類與子類(基類和派生類)
在JavaScript中,原型也是一個對象,經過原型能夠實現對象的屬性繼承,JavaScript的對象中都包含了一個[[Prototype]]
內部屬性,這個屬性所對應的就是該對象的原型。
[[Prototype]]做爲對象的內部屬性,是不能被直接訪問的。因此爲了方便查看一個對象的原型,Firefox和Chrome中提供了__proto__
這個非標準(不是全部瀏覽器都支持)的訪問器(ECMA引入了標準對象原型訪問器"Object.getPrototype(object)")。
下面經過一個例子來看看原型相關概念:
function Person() {} // 神祕對象就是Person.prototype //那麼只有使用構造函數才能夠訪問它 var o = new Person(); //之前不能直接使用o來訪問神祕對象 //如今有了__proto__後, o.__proto__也能夠直接訪問神祕對象 //那麼o.__proto__ === Person.prototype
神祕對象(原型)中都有一個屬性constructor
,翻譯爲 構造器 。表示該原型是與什麼構造函數聯繫起來的。
__proto__
有什麼用?能夠訪問原型。因爲在開發中除非特殊要求,不要使用實例去修改原型的成員,所以該屬性開發時使用較少。可是在調試過程當中很是方便,能夠輕易的訪問原型進行查當作員
若是在早期的瀏覽器中使用實例須要訪問原型如何處理?可使用實例對象訪問構造器,而後使用構造器訪問原型
var o = new Person(); o.constructor.prototype
若是給實例繼承自原型的屬性賦值
function Foo(); Foo.prototype.name = "test"; var o1 = new Foo(); var o2 = new Foo(); o1.name = "張三"; // 不是修改原型中的name而是本身增長了一個name屬性 console.log(o1.name + ','+ o2.name); // 張三,test
對於以下代碼:
function Person(){} var p = new Person() console.log(Person.prototype.constructor); //function Person(){} console.log(Person.prototype.constructor.name); //Person console.log(typeof Person.prototype.constructor); //function console.log(p.__prop__); console.log(p.__prop__ === Person.prototype);//true
因而他們的關係圖以下:
凡是對象就有原型,原型也是對象。所以凡是給定一個對象,那麼就能夠找到他的原型,原型還有原型,那麼如此下去,就構成一個對象的序列,稱該結構爲原型鏈。
問題:
凡是使用構造函數,建立出對象,而且沒有利用賦值的方式修改原型,就說該對象保留默認的原型鏈。
默認原型鏈結構是什麼樣子呢?
function Person(){} var p = new Person(); //p 具備默認的原型鏈
默認的原型鏈結構就是:當前對象 -> 構造函數.prototype -> Object.prototype -> null
在實現繼承的時候,有時候會利用替換原型鏈結構的方式實現原型繼承,那麼原型鏈結構就會發送改變
function DunizbCollection(){} DunizbCollection.prototype = []; var arr = new DunizbCollection(); // arr -> [] -> Array.prototype -> Object.prototype -> null
在JS中使用Function能夠實例化函數對象 。也就是說在JS中函數與普通對象同樣,也是一個對象類型。函數是JS中的一等公民。
要解決的問題
語法
new Function( arg0,arg1,arg1,….argN, body );
Function 中的參數所有是字符串
該構造函數的做用是將參數連接起來組成函數
舉例:建立一個打印一句話的函數
// 傳統的 function foo () { console.log( '你好' ); } //Function var func = new Function( 'console.log( "你好" );' ); // 功能上,這裏foo 與 func 等價
再好比,建立一個空函數
//傳統 function foo () {} //Function var func = new Function(); func();
傳入函數內一個數字,打印該函數
//傳統 function foo ( num ) { console.log( num ); } //Function var func = new Function( "num" ,"console.log( num )" ); func();
任意的一個函數,都是至關於Function的實例,相似於{}與new Object()的關係。
function foo () {}
上面的代告訴解析器,有一個對象叫foo,它是一個函數;至關於new Function()
獲得一個函數對象
__proto__
對於Function,咱們還必須知道
Object做爲對象是繼承自Function.prototype的,又「Function.prototype」繼承自Object.prototype
foo.prototype.__proto__ === Object.prototype // true
下面繪製出 Function 的構造原型實例三角形結構
Function是使用字符串構建函數,那麼就能夠在程序運行過程當中構建函數.
之前的函數必須一開始就寫好,再通過預解析,一步一步的運行
假定從服務器裏拿到「[1,2,3,4,5]」,將數組形式的字符串轉換成數組對象
var arr = ( new Function( 'return ' + str + ' ;' ) )();
推薦閱讀