先上一段代码,创建一个构造函数并且根据构造函数创建对象:
// 构造函数创建对象
function Dock(name,age){
this.name = name;
this.age = age;
this.sing = function(){
console.log('唱歌真好听');
}
}
var xtf = new Dock('西亭凤',18);
var xs = new Dock('许嵩',125);
console.log(xtf)
console.log(xs)
console.log(xtf.sing === xs.sing) //false
以上代码使用构造函数创建了两个对象,但是对象xtf和xs两个对象中的属性sing都是构造函数中的sing,但是这两个对象的属性sing不相等,说明通过构造函数创建的对象获取的属性sing虽然是一个函数,但是函数sing存放的地址不一样,所以他们不相等。
这时就可以用到通过构造函数的原型对象prototype来创建一个属性sing,从而使得通过构造函数创建的对象所得到的的sing属性相同,因为他们都是通过对象原型__proto__来获取的,如下:
function Dock(name,age){
this.name = name;
this.age = age;
}
Dock.prototype.sing = function(){
console.log('唱歌真好听');
}
var xtf = new Dock('西亭凤',18);
var xs = new Dock('许嵩',125);
console.log(xtf)
console.log(xs)
console.log(xtf.sing === xs.sing) //true
由上面可以得出每一个从构造函数都有一个原型也称为原型对象,构造函数可以通过原型对象让通过构造函数创建的对象共享构造函数的方法,而公共的属性可以放到构造函数里面即可,从而减少内存的占用,每一个对象都有,一个原型__proto__指向构造函数的原型prototype,而每一个通过构造函数创建的对象可以根据对象的原型__proto__属性来访问构造函数通过原型创建的方法。
除此之外,对象的原型(__proto__)和构造函数的原型对象(prototype)之中都有一个属性constructor属性,这个属性我们称之为构造函数,因为它指回构造函数本身。代码如下所示:
function Dock(name,age){
this.name = name;
this.age = age;
}
Dock.prototype.sing = function(){
console.log('唱歌真好听');
}
var xtf = new Dock('西亭凤',18);
var xs = new Dock('许嵩',125);
console.log(Dock.prototype)
console.log(Dock.prototype.constructor)
console.log(xs.__proto__)
console.log(xs.__proto__.constructor)
结果如下:
由上面代码可以看到constructor属性指向的是构造函数的本身。
但是当我们给构造函数创建等多个单独的属性的时候,比如像下面这样:
function Dock(name,age){
this.name = name;
this.age = age;
}
Dock.prototype.sing = function(){
console.log('唱歌真好听');
}
Dock.prototype.movie = function(){
console.log('演电影真好看');
}
var xtf = new Dock('西亭凤',18);
var xs = new Dock('许嵩',125);
console.log(Dock.prototype)
console.log(Dock.prototype.constructor)
console.log(xs.__proto__)
console.log(xs.__proto__.constructor)
当我们把多个属性合并成一个对象之后,再次使用构造函数的prototype属性和对象原型__proto__去获取constructor属性时,就无法获取到,因为我们把构造函数的原型值改变了,新添加的原型对象把原有的构造函数的原型对象给覆盖了,所以没有了属性constructor。
function Dock(name,age){
this.name = name;
this.age = age;
}
Dock.prototype={
sing: function(){console.log('唱歌真好听')},
movie: function(){console.log('演电影真很看')}
}
var xtf = new Dock('西亭凤',18);
var xs = new Dock('许嵩',125);
console.log(Dock.prototype)
console.log(Dock.prototype.constructor)
console.log(xs.__proto__)
console.log(xs.__proto__.constructor)
所得结果如下:
这时候我们就应该在给构造函数赋予属性的时候吧constructor属性直接表明它的构造函数是谁,以免之后出现问题,如下:
function Dock(name,age){
this.name = name;
this.age = age;
}
Dock.prototype={
constructor:Dock,
sing: function(){console.log('唱歌真好听')},
movie: function(){console.log('演电影真很看')}
}
var xtf = new Dock('西亭凤',18);
var xs = new Dock('许嵩',125);
console.log(Dock.prototype)
console.log(Dock.prototype.constructor)
console.log(xs.__proto__)
console.log(xs.__proto__.constructor)
结果如下:
这样我们就可以再次根据constructor属性找到对象或者构造函数原型对象找到构造函数本身了。
下面就用一张图来详细描述一下构造函数、对象实例、原型之间的关系: