[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

相关文章
相关标签/搜索