js中原型,原型链,原型链继承的个人理解

来源:互联网 发布:nginx怎么使用 编辑:程序博客网 时间:2024/05/22 12:03

一、什么是原型?

每一个javascript对象在创建的时候就会有一个与之关联的对象B产生,对象B就是所说的“原型”

    1)原型也是一个对象,其他对象可以通过原型实现属性继承,

    2)js中的继承就是基于原型的继承;

    3)所有对象在默认情况下都有一个原型,因为原型也是一个对象,所以每         个原型自身又有一个原型,默认的对象原型在原型链的顶端;

 

二、函数的原型对象

创建一个函数A,那么浏览器就会在内存中创建一个对象B,而且每个函数都会默认有一个prototype属性指向这个对象(即:prototype属性的值是这个对象),而对象B就是函数A的原型对象,简称函数的原型。对象B默认会有一个constructor属性指向函数A(即:constructor属性的值是函数A)。

 

 

 

三、原型相关属性

1.prototype:存在于构造函数中,指向这个构造函数的原型对象

2.__proto__:存在于实例对象中,指向这个实例对象的原型对象

3.constructor:存在于原型对象中,指向构造函数

 

举例:

functionPro(name,age){

        this.name=name;

        this.age=age;

}

     

var pro1=new Pro();

var pro2=new Pro();

 

关系:

pro1.__proto__==pro2. __proto__;

pro1.__proto__==Pro.Prototype;

Pro.prototype.constructor==Pro();

Pro.prototype.__ptoto__==Object.prototype;

Object.prototype.constructor==Object();

结论:

1pro1.__proto__pro2.prototype都指向构造函数Pro的原型对象;

2)如果使用new Person()创建多个对象,则多个对象都会同时指向Person构造函数的原型对象;

 

什么是原型链?

由图引出原型链的概念:

每个构造函数都一个prototype属性指向自身的原型,而由该构造函数创建的实例对象也都有一个__proto__属性指向该构造函数的原型,而构造函数的原型也是一个对象,它也会有一个__proto__属性指向自己的原型,这样层层深入,直到Object的原型,从而形成了原型链。

 

一个实例,至少应该拥有指向原型的proto属性,这是JavaScript中的对象系统的基础。不过这个属性是不可见的,我们称之为“内部原型链”,以便和构造器的prototype所组成的“构造器原型链”(亦即我们通常所说的“原型链”)区分开

 

 

四、原型方法

1. getPrototypeOf():获取一个对象的原型

格式:Object. getPrototypeOf(对象)

2. setPrototypeOf():设置一个对象的原型

格式:Object. setPrototypeOf(对象)

3.hasOwnProperty():用于判断一个属性是本地属性,还是继承梓prototype对象的属性

格式:对象. hasOwnProperty(’属性名’):

4.isPrototypeOf( ):判断对象a是否存在于另一个对象prototypeObject的原型链中(只有存在继承关系时该方法才有用)

格式:prototypeObject.prototype.isPrototypeOf(a)

5.instanceof:判断a是否是b的实例对象

格式:a.instanceof.b

 

 

 

 

 

五、使用prototype扩展对象的原型属性和原型方法

1.当对象被创建后,就可以使用prototype来扩展对象

Obj.prototype.method=function(){}

举例:

Function   car(){};//声明一个构造函数,即创建了一个对象

Car prototype.color=’red’;

 

 

 

六、创建对象的新方法

Object.create(obj):obj是要使用的原型,即要被继承的对象

举例:

Var  car={name:“奔驰”};

Var car1=Object.create(car);

 

给对象扩展属性和方法:

1. 对象可以继承原型的属性,也可以扩展出自己的属性和方法

举例:

      varcar={

         name:'玛莎拉蒂',

         price:'500W',

      }

     

      var car1=Object.create(car);

      car1.color='red';//定义自有属性

      car1.name='法拉第 ';//重新定义一个自有的name属性

      car1.run=function(){//扩展一个自有方法

         console.log('四驱引擎驱动');

      }

      console.log(car1.price);//继承原型的name属性

      console.log(car1.name);//法拉第

      console.log(car1.color);//red

      car1.run();

     

      //原型属性MaxSpeed

      Object.getPrototypeOf(car1).MaxSpeed='300公里/小时';

      //等价于car1.__proto__.MaxSpeed='300公里/小时';

      //给原型扩展一个新方法,所有子级对象可以继承该方法

      Object.getPrototypeOf(car1).stop=function(){

         console.log('停车');

      }

     

     

      var car2=Object.create(car);

      console.log(car2.name);//继承原型原有的属性

      //colorcar1的自有属性,其他子级对象无法继承该属性

      console.log(car2.color);

      console.log(car2.MaxSpeed);//继承新增加的原型属性

      car2.stop();//继承新扩展的方法stop

     

      //修改原型属性name,使得所有子级对象的name属性值全部改变

      Object.getPrototypeOf(car1).name='比亚迪';

      var car3=Object.create(car);

      console.log(car2.name);

      console.log(car3.name);

     

      delete car1.name;//删除自有属性

    console.log(car1.name);//比亚迪

 

 

 

 

 

 

 

 

 

 

 

 

七、原型链的继承


这种方法最常用,安全性也比较好。我们先定义两个对象:

function Animal(name){
this.name = name;

}
function Dog(age) {
  this.age = age;
}
var dog = new Dog(2);

 

要构造继承很简单,将子对象的原型指向父对象的实例(注意是实例,不是对象)

Dog.prototype = newAnimal("wangwang");

 

这时,dog就将有两个属性,name和age。而如果对dog使用instanceof操作符

console.log(doginstanceof Animal); // true
console.log(dog instanceof Dog); // false

 

这样就实现了继承,但是有个小问题

console.log(Dog.prototype.constructor ===Animal); // true
console.log(Dog.prototype.constructor ===Dog); // false

 

可以看到构造器指向的对象更改了,这样就不符合我们的目的了,我们无法判断我们new出来的实例属于谁。因此,我们可以加一句话:

Dog.prototype.constructor = Dog;

 

再来看一下:

console.log(dog instanceof Animal); // false
console.log(dog instanceof Dog); // true

 

这种方法是属于原型链的维护中的一环

 

例2完整代码:实现让Child构造函数的原型继承Parent.prototype的getName方法

functionParent(name){

             this.name=name

           }

          function Child(name){

             this.name=name

           }

           Parent.prototype.getName=function(){

             return this.name;

           }

          

           Child.prototype=newParent();//实现继承

           Child.prototype.constructor=Child;//原型链的维护

          

           var parent=newParent('parent');

          var child=newChild('child');

          console.log(parent.getName());

          console.log(child.getName());

          

       console.log(Child.prototype.constructor==Child);