今天通俗讲解一下js的对象,因为要通俗,所以可能描述不甚准确。
在js中,想要创建一个对象,首先要写出构造函数(跟其它的语言不太一样哦,其它语言一般都会先写一个class 类名)。
构造函数写法如下(其实就是一个普通函数,不过,我们一般遵循类名第一个字母是大写的风俗,写成Person,其实写成person也没问题):
//Person是构造函数
function Person(name,age)
{
this.name=name;
this.age=age;
}
有了构造函数后,new一下构造函数,就会产生出一个“实例对象”。
//p1是实例对象
var p1=new Person("张三",20);
console.log(p1)
有了实例对象p1后,p1有一个constructor属性,这个属性等于它的构造函数
console.log(p1.constructor === Person)
这就是一个对应关系:
构造函数--------------new-------------实例对象
实例对象 --------constructor--------构造函数
那么,这个构造函数、实例对象所对应的原型对象(类)是什么呢?
来了,在构造函数Person有一个prototype的属性,它就指向原型对象(类)。
console.log(Person.prototype)
运行结果(原型对象,而且其中有一个构造函数Person。【类中就是应该有一个构造函数】):
构造函数--------------new-------------实例对象
实例对象 --------constructor--------构造函数
构造函数-----------prototype---------原型对象(类)
原型对象(类)----constructor----构造函数
好,既然有了原型对象(类),那么,我就可以在类中添加方法了。
//在原型对象(类)中添加方法
Person.prototype.eat=function(){
console.log('吃饭');
}
既然类中有了新的方法,那么刚才生成的实例对象p1,也应该有这个新方法了,确认一下:
运行结果(证明是可以的):
至此,我们建立了如下关系:
构造函数--------------new-------------实例对象
实例对象 --------constructor--------构造函数
构造函数-----------prototype---------原型对象(类)
原型对象(类)----constructor----构造函数
似乎缺少点什么?
是的,那就是实例对象和原型对象(类)之间的关系。
刚才的测试我们已经可以确认,如果在类中添加了新的方法,对应的实例对象中,也可以使用这个方法,那么实例对象和原型对象(类)之间怎么建立的这种联系呢?
直接给出:实例对象中有一个__proto__属性,指向了原型对象(类)。
实例对象 ---------__proto__---------原型对象(类)。
下面有来了新的问题,实例对象p1中,并没有eat的方法【eat方法是原型对象(类)中的方法】,如下图
、
那么,实例对象(p1)为何能使用原型对象类(Person.prototype)中的方法呢?
方法:实例对象先看自己有没有这个方法,若有,执行;若没有,通过 __proto__找到上一级类看是否有方法,如果还没有,继续往上找,直至类成为null。
这就是原型链。
本质上是种“类的继承”的解决方法。
所以,全面的关系如下:
构造函数-------------->new------------->实例对象
实例对象 -------->constructor-------->构造函数
构造函数----------->prototype--------->原型对象(类)
原型对象(类)---->constructor---->构造函数
实例对象 --------->__proto__>---------原型对象(类)
最后再说一点,其实可以在浏览器的console中看到原型链的情况。
构造函数Person生成的实例对象p1,只有age,name,sleep(),如果运行p1.eat(),其会通过__proto__找到它的原型函数中的eat()执行。