为了解决从原型对象生成实例的问题,Javascript提供了一个构造函数(Constructor)模式。
所谓“构造函数”,其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。
function Cat(name,age){ this.name = name; this.age = age; }
我们可以生成实例对象了
var cat1 = new Cat('小猫','14'); var cat2 = new Cat('大猫','4'); console.log(cat1.name);//小猫 console.log(cat2.age);//4
这时cat1和cat2会自动含有一个constructor属性,指向它们的构造函数
console.log(cat1.constructor === Cat);//true console.log(cat2.constructor === Cat);//true
Javascript提供了一个instanceof运算符,验证原型对象与实例对象之间的关系
console.log(cat1 instanceof Cat);//true console.log(cat2 instanceof Cat);//true
因为构造函数有一个弊端,对于每一个实例对象,每一次生成一个实例,都必须为重复的内容,多占用了内存。所以,我们采用Prototype模式来解决这个问题。
Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。
这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上。
function Cat(name, age) { this.name = name; this.age = age; } Cat.prototype.type = '猫科动物'; Cat.prototype.eat = function() { console.log('吃老鼠') };
然后,生成实例。
var cat1 = new Cat('大猫',12); var cat2 = new Cat('小猫',5); console.log(cat1.type); cat2.eat();
这时所有实例的type属性和eat()方法,其实都是同一个内存地址,指向prototype对象,因此提高了运行效率。
console.log(cat1.type === cat2.type);//true
Prototype模式的验证方法
isPrototypeOf()这个方法来判断,某个prototype对象和某个实例之间的关系。
console.log(Cat.prototype.isPrototypeOf(cat1));//true
每个实例对象都有一个hasOwnProperty()方法,用来判断某一个属性到底是本地属性,还是继承自prototype对象的属性
console.log(cat1.hasOwnProperty('name'));//true console.log(cat2.hasOwnProperty('type'))//false