首先需要说明的是通过构造函数来创建对象的方法有很多,es6之后是通过class来创建对象的。那么今天就用构造函数的方式来创建对象。
我理解的通过构造函数来创建对象,实际上就是把公共的属性和方法封装成函数,然后实例化。
下面来创建一个简单的构造函数
function Star(name, age) {
this.name = name;
this.age = age;
this.sing = function() {
console.log('唱歌');
}
}
var ldh = new Star('刘德华', 18); // 创建一个空对象
通过实例化创建Star这个对象,这个对象里面有一些公共的属性和方法,那么实例化之后要想使用这些方法,是通过实例化对象来获取的,而不是通过构造函数来获取的,但是有一点需要注意的是,静态成员只能通过构造函数来访问,实例成员只能通过实例化对象来访问。
但是呢会存在一个问题,如果需要实例化对象很多的话,那就会在内存中开辟很多空间,而且有些方法是一样的,就会造成内存浪费。正因为这个问题的存在,这时就引出了prototype原型对象,每一个构造函数都有这个属性,作用就是共享方法,可以把一些共有的方法和函数定义到原型上,这样的话所有对象的实例都能共享这个方法
function Star(uname, age) {
this.name = uname;
this.age = age;
}
Star.prototype.sing = function() {
console.log('唱歌');
}
var ldh = new Star('刘德华', 18);
var zxy = new Star('张学友', 19);
console.log(ldh.name);
console.log(zxy.name);
把sing这个方法定义到原型上就可以实现共享方法,那么接下来问题又来了,为什么把sing方法定义到原型上,这些实例化对象就能访问了?
其实每个对象都有一个对象原型__proto__,而这个对象原型指向的是构造函数原型,也就是prototype,其实也就是实例化对象原型就等于构造函数的原型对象。需要注意的是,只有函数function才具有prototype属性。这个属性是一个指针,指向一个对象,这个对象的用途就是包含所有实例共享的属性和方法(我们把这个对象叫做原型对象)。原型对象也有一个属性,叫做constructor,这个属性包含了一个指针,指回原构造函数。
console.log(ldh.__proto__ === Star.prototype); //true
这就说明了可以通过实例化对象来访问构造函数的原型对象上的方法