上一篇最后讲构造函数的一个缺陷,就是浪费内存, 虽然函数方法是一样的但是他们的内存地址是不同的,也就是说一人开辟了一个内存空间,开了两个。
这就需要引入构造函数原型prototype的概念了
那么原型和构造函数什么关系呢
构造函数通过【原型】分配的函数是所有对象所【共享的】。
JS规定,
每一个【构造函数】都有一个【prototype】属性,指向另一个对象。
注意这个prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。
我们可以把那些不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以【共享】这些方法。
一般情况下,我们的公共属性定义到构造函数里面,而公共的方法我们放到原型对象的身上,因为方法是需要开辟内存空间的 这样同样的方法只需要开辟一个内存空间就可以了。
【对象】都会有一个属性 __proto__
( 这里是杠杠proto杠杠是 前后均是两个下划线)
它所指向的是构造函数的prototype【原型对象】,之所以对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有__proto__
原型的存在。
接上一篇案例 Star明星 实例化的刘德华 张学友
ldh.__proto__ === Star.prototype // true
简单的理解 :
构造函数下的实例比如 ldh 要指向原型使用原型对象的话使用__proto__
而构造函数比如Star 要指向原型使用原型对象使用prototype
他俩的指向是他们所共有的原型对象。
而原型对象prototype有一个 constructor方法可以指回构造函数 如"Star"
同理:对象实例的
ldh.__proto__是原型对象prototype 那么ldh.__proto__.constructor就是 构造函数本身了 如"Star"
查找方法也是就近原则 没有就通过__proto__
往上查找
ldh.__proto__ === Star.prototype ===Obj
Obj里面含有 方法名、__proto__、constructor
而这个 constructor === function Star(){}
constructor 用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。
如果添加方法名不是用的 "."
Star.prototype.xxx = function(){}
而是用对象的形式添加
Star.prototype = {
xxx: function(){},
xxx1:function(){}
}
这就不是添加了 而是【覆盖】。把原来的constructor也覆盖掉了也就是不存在constructor了
解决方法:
如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数
在第一行写入constructor:Star,
Star.prototype = {
constructor:Star,
xxx: function(){},
xxx1:function(){}
}