[JS相關的記錄01] 那什麼來面對你,面向對象編程(__proto__,prototype,constructor以及原型鏈)

老是據說面向對象,類,繼承,__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;
}

結果就正確了......

又查了一下,總結一下:

  1. 全部的對象都有__proto__屬性,該屬性對應該對象的原型.

  2. 全部的函數對象都有prototype屬性,該屬性的值會被賦值給該函數建立的對象的_proto_屬性.

  3. 全部的原型對象都有constructor屬性,該屬性對應建立全部指向該原型的實例的構造函數.

  4. 函數對象和原型對象經過prototype和constructor屬性進行相互關聯.

雖然說弄懂了些表面的東西,實際上最主要的緣由仍是沒明白,那就是原型鏈到底有什麼用呢?

好了,以上就是今天總結的一些內容,但願相互學習幫助,可以在將來更好的工做生活。
信息來源:

(↓相關一些對我幫助很大,Git的學習就是在這裏看的,說的很詳細也很生動↓)
廖雪峯JavaScript教程
JS原型、原型鏈深刻理解
深刻分析js中的constructor 和prototype

相關文章
相關標籤/搜索