原型及原型链继承之间的关系

178 阅读3分钟
什么是原型?
1.原型产生的原因
	实例化其实是一个很耗费内存空间的,通过构造函数去实例对象的时候,每一个对象中的属性和方法都是在自己的空间,那么当有多个对象的时候,这些属性和方法就有多少个在各自的空间中存在在,所以很浪费空间,因此,为了解决这个问题,实现数据共享,原型就产生了。

2.构造函数中有个prototype,是原型,也是我们平时所使用的

3.而我么通过构造函数所实例化的对象中-Proto-属性,这也是原型,是浏览器使用的,这个下划线原型指向的就是该实例对象中的构造函数中的prototype

4.如何访问的到函数中的prototype呢?

	实例对象.__proto__  这样就可以实现访问prototype中的属性和方法啦
        function Person(name){
            this.name = name ;
        }
        Person.prototype.play = function(){
            console.log('打球');
        }
        var p1 = new Person('cimei');
        p1.play();
        console.dir(Person);//查看构造函数的结构
        console.dir(p1);//查看实例对象的结构
        console.log(p1.__proto__== Person.prototype)//看他们的指向是否一致,此处结果是true

在这里插入图片描述

原型的指向问题

构造函数中的this就是实例对象(谁调用的就是谁的)

原型对象中的方法中的this就是实例对象

//Person的构造函数
	  function Person(name){
            this.name = name;
        }
//Person的原型对象上的方法
        Person.prototype.play = function(){
            console.log('打球');
        }
//Subject的构造函数
        function Subject(age){
            this.age = age;
        }
//Subject的原型对象上的方法
 		Subject.prototype.eat = function(){
            console.log('今天吃饺子');
        }
//Subject的原型,指向了Person的实例对象
        Subject.prototype = new Person('cimei');
        var sub = new Subject(18);
//此时发现可以调用Person原型上的方法
        sub.play();
//此时会报错
		sub.eat();

在这里插入图片描述

黑色线是真正的走向,红色的线是被改变了的,已经不存在了。

总结:
实例对象的原型__proto__指向的是该对象的构造函数的原型对象

构造函数的原型对象prototype 指向如果改变了,那么实例对象的原型__proto__指向自然也就会跟着改变

原型链

其实实例对象与构造函数并没有直接的关系,两者之间的关系就通过实例对象中的那个__proto__和原型对象(prototype)来联系的。而我们也称之为原型链

原型指向改变的话如何添加方法并访问呢?

1.如上述例子,改变了Subject的原型的指向,发现调用不了原来Subject原型上的方法了

解决办法:可以在原型改变之后 再添加在其原型上添加方法。

2.访问属性或方法

说白了,就是就近原则,实例对象有的话,就直接用,实例对象上没有,就去原型对象上找。这里有个问题,就是如果找不到也不会报错,会返回一个undefined,因为js是一门动态类型的语言,对象没有的话,只要有点(.),那么这个对象就有了这个东西,没有我们要的这个东西,只要有对象.属性这个名字,对象就有了这个属性,但是还没有给其赋值,所以是undefined的。总结就是js有立即创造属性的能力,大方的很,你没有,我就给你一个。

封装:其实就是把一些相似的对象放在js文件按中

继承:js中的继承是通过构造函数去模拟类,然后通过原型来实现的。其中原型实现了数据的共享,为我们节约了内存空间。

属性的继承体现在构造函数的继承上,调用父类的构造函数使用call,apply,方法的继承就是prototype的指向问题了

那么原型的作用也就有了两个:一是节约了内存空间,二是实现了继承

多态:一个对象有不同的行为,或者是一个行为针对不同的对象,产生不同的结果,要想实现多态,就要先有继承