浅谈原型、原型链与继承

一、原型

1.那么首先,什么是原型呢?

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

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

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

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

2.原型的定义及一些特点:

(1) 定义:原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。
通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。
(2) 利用原型特点和概念,可以提取共有属性。
(3) 对象如何查看原型 — > 隐式属性 __proto__。
(4) 对象如何查看对象的构造函数 — > constructor。
(5) 每个对象都有 __proto__ 属性,但只有函数对象才有 prototype 属性

3.原型相关属性

(1) prototype:存在于构造函数中,指向这个构造函数的原型对象
    
(2) __proto__:存在于实例对象中,指向这个实例对象的原型对象

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

(4) 若一个构造函数没有指定其原型,则其原型默认为Object.prototype

举例:
	    function Pro(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();
	    
	    结论:	    
	    (1) pro1.__proto__和pro2.prototype都指向构造函数Pro的原型对象;	    
	    (2) 如果使用new Person()创建多个对象,则多个对象都会同时指向Person构造函数的原型对象;

4. 原型方法

(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

二、原型链

1.那么首先,什么是原型链呢?

请看图:

    A.protorype = { name: 'a' }
    
     	function A() ( this.name = 'A'; )
        
     		B.prototype = new A();
        
    			 function B() { this.name = 'B'; }
        
    				 C.prototype = new B();
        
     					function C(){ this.name = 'C'; }


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

2.原型链上属性的增删改查:

- 查:优先去实例对象上寻找是否有该属性,若没有,则再去其对应的原型上去寻找该属性,
      若都没有,则返回undefined
              
- 增:直接给实例对象增添属性,则仅仅在实例对象上增添属性,若在原型上增添属性,
	则在原型上增添属属性,则在原型上增添属性,其实例继承原型增添的属性。
                 
- 删:delete仅仅能删除实例对象的属性,即构造函数原有的自己的属性和后来实例对象
	增添的属性,还有关于delete的一点需注意,delete无法删除原型的属性和用var
	定义的变量(即非window的属性)
    
- 改:更改实例对象的属性,则仅仅更改实例对象的属性值;更改原型的属性值,
	则更改原型的属性值,继承该原型的对象对应属性值也会被更改;

三、继承

1.原型链是ECMAScript标准指定的默认继承方式

对象继承的发展:

(1) 传统模式:即正常的通过构造函数创建实例对象,来继承原型
缺点:继承了过多不必要的属性
(2) 借用其他构造函数(即通过call / apply来改变构造函数内this对象的引用)
缺点:无法继承借用构造函数的原型

    

			A.prototype = {
				    name: 'a',
				    age: 18,
				    class: 1
			    }
			    function A(){
			        this.name = 'A';
			    }
			    function B(){
			        A.call(this);
			    }
			    var b = new B();
			    console.log(b.name); // A
			    console.log(b.age) // undefined

(3) 共享原型:即将其他构造函数的原型直接赋值给本构造函数的原型
缺点:两个原型会想回影响,更改其中一个原型,更一个对应的原型也会被更改。

A.prototype = {
        name: 'a',
        age: 18,
        class: 1
    }
    function A(){
        this.name = 'A';
    }
    B.prototype = A.prototype;
    function B(){
        this.name = 'B';
    }
  C.prototype = A.prototype;
  function C() {
    this.name = "C";
  }

    var a = new A();
    var b = new B();
    var c = new C();
    console.log(a.age); // 18
    console.log(b.age); //18
    console.log(c.age); //18


    // 原型继承成功
    B.prototype.age = 20; //更改其中一个原型的age属性
    console.log(b.age);//20
    console.log(c.age); //20
    // 继承A原型的B和C相互影响

(4) 圣杯模式:

每次继承的都是新创建的F构造函数实例,相互之间不会影响。其实此处针对F形成了闭包,Child引用了F,导致F不会销毁。

  • 正常函数形式:

function inherit (Child, Parent) {
        // 借用F这个中间量来继承,而不是直接共享原型
        var F = function (){}
        F.prototype = Parent.prototype;
        Child.prototype = new F();
        // 自定义构造函数原型时,同时要更正自定义原型的constructor,否则一般默认为Object(),次函数若不指定constructor,则constructor为Parent
        Child.prototype.constructor = Child; 
        
        Child.prototype.uber = Parent; //记录真正继承的是谁
    }

  • 闭包形式:

    var inherit = (function(){
        var F = function (){};
        return function (Child, Parent) {
            F.prototype = Parent.prototype;
            Child.prototype = new F();
            Child.prototype.constructor = Child;
            Child.prototype.uber = Parent;
        }
    })();
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值