老是據說面向對象,類,繼承,__proto__,prototype,constructor.......因而乎小整理一下。html
首先說,JS裏的繼承是怎麼弄的呢?函數
首先建立類(Person)學習
var Person = { male: 0, age:0, name:'nothing', say:function(){ console.log('Hello World'); } }
如何建立一我的呢?this
var createPerson = function(){ return Object.create(Person); }
建立學生.net
var Student = createPerson(); Student.say() //Hello World Student.__proto__ === Person //true Student.constructor === Person //Student的構造器仍是Object
從這個能夠看出什麼呢?能夠看出所謂的繼承,就是下面的代碼而已:prototype
SSSSS.__proto__ = BBBBB
可是呢?也沒有prototype啥關係嘛,由於壓根就和他不要緊,好像也不太好,換一種寫法好了。code
function Person (props){ this.name = props.name || 'nothing'; this.male = props.male || 0; this.age = props.age || 0; this.say = function(){ console.log('Hello world!'); } }
繼續建立studenthtm
var Student = new Person(); Student.__proto__ === Person.prototype //true Student.constructor === Person //true Student.say() //Hello world!
從上面代碼能夠看出,Student繼承了Person.
若是咱們想改變一下呢?對象
Student.say = function(){ console.log('Hello teacher, my name is ' + this.name);//Hello teacher, my name is nothing }
那好,再建立一個coder類blog
var Coder = new Person(); Coder.say(); //Hello world!
這個不錯嘛,這樣在想建立Coder的子類,js和html,那就修改一下代碼
function Coder (props){ Person.call(this,props); this.tip = props.tip?props.tip.toUpperCase():''; this.intro = function(){ console.log('I know '+(this.tip?this.tip:'nothing')); } this.say= function(){ console.log('hello, my name is ' + this.name); } } var JSer = new Coder({ name:'Tony', age:26, tip:'js' }); var htmler = new Coder({ name:'Jermy', age:26, tip:'html' }); JSer.say(); //hello, my name is Tony htmler.say(); //hello, my name is Jermy JSer.intro(); //I know JS htmler.intro();//I know HTML
這樣獲得了咱們想要的結果,驗證一下繼承關係:
JSer instanceof Coder; //true htmler instanceof Coder;//true Coder instanceof Person;//false
這樣就很差了,爲何不是繼承關係呢?查看一下Coder狀況如何?
Coder.__proto__ === Person.prototype; //false Coder.__proto__ //function () { [native code] }
看來問題就出在這裏,寫一箇中間函數補充一下?
var pass = function(child,parent){ var F = function(){}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; }
爲了實現這一點,參考道爺(就是發明JSON的那個道格拉斯)的代碼,中間對象能夠用一個空函數F來實現,大神寫的代碼,就是特麼讓人深思。
仔仔細細想了下,我我的是這麼理解的。
首先定義空函數這個不用解釋,而後把這個空函數的原型指向爲Parent的原型,而後再把Child的原型指向這個新的F對象,一個完美傳遞;
最後,在把Child原型的構造方法定義成Child;
華麗的轉身,結果以下:
function Coder (props){ Person.call(this,props); this.tip = props.tip?props.tip.toUpperCase():''; this.intro = function(){ console.log('I know '+(this.tip?this.tip:'nothing')); } this.say= function(){ console.log('hello, my name is ' + this.name); } } var pass = function(Child,Parent){ var F = function(){}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; } pass(Coder, Person); var JSer = new Coder({ name:'Tony', age:26, tip:'js' }); var htmler = new Coder({ name:'Jermy', age:26, tip:'html' }); JSer.say(); //hello, my name is Tony htmler.say(); //hello, my name is Jermy JSer.intro(); //I know JS htmler.intro();//I know HTML JSer instanceof Coder; //true htmler instanceof Coder;//true Coder instanceof Person;//false
結果仍是不對,因而我又在大神的肩膀上墊了一下腳。
var pass = function(Child,Parent){ var F = function(){}; F.prototype = Parent.prototype; Child.__proto__ = new F(); Child.__proto__.constructor = Child; }
結果就正確了......
又查了一下,總結一下:
全部的對象都有__proto__屬性,該屬性對應該對象的原型.
全部的函數對象都有prototype屬性,該屬性的值會被賦值給該函數建立的對象的_proto_屬性.
全部的原型對象都有constructor屬性,該屬性對應建立全部指向該原型的實例的構造函數.
函數對象和原型對象經過prototype和constructor屬性進行相互關聯.
雖然說弄懂了些表面的東西,實際上最主要的緣由仍是沒明白,那就是原型鏈到底有什麼用呢?
好了,以上就是今天總結的一些內容,但願相互學習幫助,可以在將來更好的工做生活。
信息來源:
(↓相關一些對我幫助很大,Git的學習就是在這裏看的,說的很詳細也很生動↓)
廖雪峯JavaScript教程
JS原型、原型鏈深刻理解
深刻分析js中的constructor 和prototype