原本打算也寫一個JavaScript學習筆記的系列,不過因爲筆者不太想買大部頭的js數據,和網上的資料也很多,因此js系列就打算寫到了算了了。編程
要理解JavaScript就要理解其原型,首先咱們先區分一下JavaScript中的兩種不一樣方式建立的函數;框架
1 function foo1(){} 2 console.log(foo1.prototype); 3 console.log(foo1.__proto__); 4 5 var foo2 = function() {} 6 console.log(foo2.prototype); 7 console.log(foo2.__proto__);
這裏有兩個屬性prototype和__proto__,咱們來看他們分別指向什麼。函數
咱們在看看foo1.prototype包含的屬性:學習
1 function foo(){} 2 console.log(foo.prototype.__proto__ === Object.prototype);//true
能夠看見,原型對象的__proto__指向其父級對象的prototype;this
1 function foo(){} 2 var a = new foo(); 3 console.log(a.prototype);//undefined 4 console.log(a.__proto__);//Object
經過輸出咱們能夠發現,經過new獲得的對象,prototype屬性是空的,而__proto__則被賦予了一個對象,看下面的代碼:spa
1 function foo(){} 2 var a = new foo(); 3 console.log(a.__proto__ === foo.prototype);//true
js將foo的原型屬性賦予了用new關鍵字建立的a對象;prototype
咱們看看使用new關鍵字js爲咱們作了什麼操做;code
好比下面的代碼:對象
var a = new foo();
能夠理解爲調用了下面的代碼:blog
1 var a={};//也就是說,初始化一個對象a; 2 a.__proto__=foo.prototype;//賦值原型鏈; 3 foo.call(a);//也就是說構造a,也能夠稱之爲初始化a;
咱們再來看看js的原型繼承,js中的繼承是經過原型鏈來體現的,簡單的說,當咱們調用一個屬性時(方法在js中也是以屬性的形式存在的),會先查找自身是否有該屬性,若是沒有則查找原型上是否存在該屬性,若是仍是沒有,則查找原型上的__proto__(即父類的原型)裏是否有該屬性,若是沒有則一致搜索到最頂級(即Object的原型),找到則返回該屬性的值,找不到則返回undefined。
咱們看下下面的代碼:
1 var foo = function(){ 2 var a = 0; 3 this.a = 1; 4 }; 5 foo.prototype.a = 2; 6 foo.prototype.b = "b"; 7 console.log(foo.a);//undefined 8 foo.a = 4; 9 foo.c = 5; 10 console.log(foo.a);//4 11 12 var obj = new foo(); 13 console.log(obj.a);//1 14 console.log(obj.b);//b 15 console.log(obj.c);//undefined
咱們分析一下:
若是按面向對象的思惟來看,能夠這麼理解:
1 //建立類 Foo,按通常的規則類名首字母大寫 2 var Foo = function(){ 3 this.a = 1;//建立一個公開的屬性a 4 }; 5 //建立一個公開的方法 add 6 Foo.prototype.add = function(a, b){ 7 return a + b; 8 } 9 //建立一個靜態變量 num 10 Foo.num = 100; 11 //建立一個靜態方法 subtract 12 Foo.subtract = function(a, b){ 13 return a - b; 14 } 15 16 //調用靜態屬性及方法 17 console.log(Foo.subtract(Foo.num, 11));//89 18 //調用對象屬性及方法 19 var obj = new Foo(); 20 console.log(obj.add(obj.a, Foo.num));//101
目前咱們知道了使用js來模擬編寫一個類的方法,即如何封裝咱們知道了,可是面向對象編程還有兩個重要的特性:繼承和多態;
可是因爲js是沒有類型的概念的,因此多態這個特性咱們能夠忽略,那麼js如何使用原型來實現類繼承的效果呢?
實際上,有不少方法能夠實現類繼承的效果,或者複雜,或者簡單,接下來的兩篇文章,我會介紹兩種js實現類繼承的方法:
以上方式你們能夠二選一,固然也可使用別的方法;
最後說一下,最新的js標準ES6中,已經支持class關鍵字來定義類了,不過在ES6還沒有普及的這幾年,爲了兼容更多的用戶仍是乖乖使用老的方式吧;