实例对象与构造函数的关系?
实例对象通过构造函数创建。
通过构造函数创建实例对象的缺点是什么?
通过相同构造函数创建的对象,调用的函数相同,但比较它们的方法,结果是不相等的,说明这两个方法不是同一个方法或者说这两个方法指向的不是同一个地址,会浪费内存空间。
原因在于eat被赋值的是一个匿名函数,若换成命名函数,结果便是相同的。
但这样重新创建一个命名函数,就会存在函数名与其他变量名冲突的情况,为了避免这样的情况,使用原型来解决这个问题,即原型可以共享数据。
------------------------------------------------------------------
在实例对象中有__proto__属性(IE8不支持此属性),类型是对象,不是标准属性,供浏览器使用的。
-------------------------------------------------------------------
在构造函数中有prototype属性,类型是对象,是标准属性,供程序员使用的。
--------------------------------------------------------------------
因为prototype的类型是对象,通过这个对象共享属性和方法,还可以写成
这样的写法,需要手动指明constructor构造器。
----------------------------------------------------------
构造函数,实例对象,原型对象
构造函数可以实例化对象
构造函数中有一个属性叫prototype,指向构造函数的原型对象(原型对象是一种概念,你可以理解成{}大括号,只是它用prototype属性描述,具有共享数据的特性)。
构造函数的原型对象中有一个constructor构造器,指向自己的构造函数。
实例对象的(__proto__)指向的是构造函数的prototype。
构造函数的(prototype)中的方法可以有实例对象直接访问。
------------------------------------------------
原型中的方法是可以相互访问的。
------------------------------------------------------------
当构造函数与原型对象中出现了相同的属性和方法时,优先使用构造函数中。
------------------------------------------------------------------------
原型链:实例对象和原型对象之间的关系,通过_proto__属性联系起来
改变prototype的指向
在创建对象之前,默认是将构造函数中的prototype指向了原型对象,如上图在创建学生对象之前,将Student构造函数的prototype指向了原型对象{}
当前的stu实例对象中是没有任何方法的,原型对象也没有任何方法,所以调用eat方法回报错。
若要改变原型的指向,只要将构造函数的prototype 指向非当前构造函数的prototype即可。
这时,相当于stu实例对象拥有了Person的prototype对象中的方法和属性,但自身的Student的prototype中的方法将不属于自身,相当于切断了关系。
---------------------------------------------------------------------
也可以通过间接的方式指向其他的实例对象。
更准确的说:
Stu实例对象的__proto__属性指向自身构造函数的prototype,但自身的prototype指向了Person的实例对象中的__proto__,而Person实例对象中的__proto__指向的是Person的prototype.
---------------------------------------------------------
那么如何为自身添加方法呢?
只要你改变prototype指向之后,再在prototype上添加方法即可。
---------------------------------------------------------------
若使用如下方法,将是对对象进行覆盖。
这里prototype.eat 相当于如下图。
显然,重新赋值,会将之前的对象覆盖。
原型链的基本形式是:
实例对象的__proto__--->构造函数的prototype,中的对象
构造函数的prototype中的__proto__ --->Object的prototype中的对象
Object的prototype中的__proto__--->Null的prototype中的对象
-----------------------------------------------------------------
继承
继承的实质是改变原型的指向。
例子:人都有姓名,性别,年龄,吃饭,行走,睡觉
学生具有人的一切特性,那么学生可以继承人,学生还有自己特性。
这里stu.prototype指向学生的实例,连同学生构造函数的属性都会被继承。
但如果这么做的话,多创建几个stu对象,在new Person()传递参数时,已经写死,所有创建的学生对象都叫lvan,如何解决该呢?
组合继承(借用构造函数+改变原型指向)
在Student构造函数中通过call的方法,以当前学生对象的名义调用person函数,这样在创建学生对象的时候,就可以初始化各自参数了。另外在建立人与学生的联系时,只要new Person()不传递任何参数即可。此方法称为组合继承。
----------------------------------------------------------------------------
拷贝继承