Loading

JavaScript-原型对象与原型链

 

原型对象

1.每个对象一定会有一个原型对象

2.原型对象实际是构造实例对象的构造器中的一个属性,只不过这个属性是个对象

3.这个原型对象中的属性与方法,都会被对象实例所共享(类似python中的类方法,类属性)

4.但,原型对象的属性不是对象实例的属性,只要修改原型对象上的属性和方法,变动就会立刻体现在所有对象实例上。

5.JavaScript对每个创建的对象都会设置一个属性__proto__ ,指向它的原型对象xxx.prototype。

 

比如按照传统方法创建一个构造器

function Person(firstname,lastname,age,eyecolor)
{
    this.firstname=firstname;
    this.lastname=lastname;
    this.age=age;
    this.eyecolor=eyecolor;
    this.changeName=changeName;
    function changeName(name)
    {
        this.lastname=name;
    }
}

实例化

var person1=new Person("John","Doe",50,"blue");
var person2=new Person("Sally","Rally",48,"green");

如上面person1和person2的changeName实际是绑定在实例上的

person1.changeName === person2.changeName 

...false

person1.changeName === Person.changeName 

...false
//因为this绑定实例,所以方法都是各自实例独立的方法。所以说this跟python中self类似

如果想要一种所有实例共享的方法或属性,那只有给Person.prototype中添加修改方法或属性,则person1和person2都会得到更新,且person1.__proto__ 等同于Person.prototype

Person.prototype.changeName2= function (name)
    {
        this.lastname=name;
    }

person1.changeName2 === person2.changeName2;

...true

person1.__proto__ === person2.__proto__;

...true
person1.__proto__ === Person.prototype;

...true
person1.__proto__

...{changeName2: ƒ, constructor: ƒ}

上面person1.__proto__(即Person.prototype)除了changeName2属性外,还有一个constructor属性,这个是指向创建当前对象的构造函数

person1.__proto__.constructor
...
ƒ Person(firstname,lastname,age,eyecolor)
{
    this.firstname=firstname;
    this.lastname=lastname;
    this.age=age;
    this.eyecolor=eyecolor;
    this.changeName=changeName;
    function changeNa…

 

原型链

1.由于xxx.prototype也是个某个构造器的实例对象,所以它也有__proto__指向一个原型对象yyy.prototype,所以会成链

2.原型链的顶端或源头,是Object.prototype(有点像基因链呀,继承也是通过这条链实现的)

3.读取实例对象的某个属性或方法时,JavaScript引擎按照 对象-->原型对象a-->a的原型对象b----,最后到Object.prototype如果还是找不到,就返回undefined

4.如果实例对象属性和原型对象属性名一样,同python,优先实例自身的属性

 

按照上面例子构造一个继承Person的构造器

class Teacher extends Person{
    constructor(firstname,lastname,age,eyecolor,subject) {
        super(firstname,lastname,age,eyecolor);
        this.subject = subject;
        }
    teach(){
        console.log(this.subject);
    }
}

实例化

var teacher1=new Teacher("Tim","D",25,"blue","math");

在实例中查看原型链的情况

>>>teacher1.__proto__

...Person {constructor: ƒ, teach: ƒ}

>>>teacher1.__proto__.constructor

...class Teacher extends Person{
    ...
}

>>>teacher1.__proto__.__proto__

...{changeName2: ƒ, constructor: ƒ}

>>>teacher1.__proto__.__proto__.constructor

...function Person(firstname,lastname,age,eyecolor)
{
    ....
}

>>>teacher1.__proto__.__proto__.__proto__

...{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}

>>>teacher1.__proto__.__proto__.__proto__.constructor

...Object() { [native code] }

>>>teacher1.__proto__.__proto__.__proto__.__proto__

...null

可以发现teacher1的原型链是 Teacher.prototype ---> Person.prototype ---> Object.prototype ---> null

 

posted @ 2019-06-13 10:23  fengf233  阅读(381)  评论(0编辑  收藏  举报