Javascript构造函数、原型、对象

时间:2022-08-24 23:13:20

构造函数与原型

构造函数是生成对象的模板,一个构造函数可以生成多个对象,每个对象都有相同的结构。使用new调用构造函数会自动创建一共新对象,调用构造函数的一共重要特征是,构造函数的prototype属性会被用作新对象的原型。

构造函数的缺点就是,每当你实例化两个对象时,需要调用两次构造函数的某一个方法,这带来的坏处就是占用内存。

为了解决构造函数的属性和方法无法被对象实例所共享的问题,我们可以把需要共享的属性和方法放在原型(prototype)对象上。原型对象上的所有属性和方法,都会被对象实例所共享。

function Animal(){}
var anim = new Animal();

每个javascript函数都自动拥有一共prototype属性,该属性是一个对象

\\true
Animal.prototype.__proto__ == Object.prototype

prototype对象包含一个constructor的属性,该属性指向函数自身

\\true
Animal.prototype.constructor == Animal

当使用new调用构造函数时,会创建一个新对象,新对象的有一个__proto__属性,该属性指向构造函数的prototype。

下面图中概括了js对象、原型、构造函数之间的关系。
Javascript构造函数、原型、对象


原型继承

js是一门基于原型的语言,在其他面向对象语言中,例如Java,一个类继承于另一个类,而js则是从另一个对象继承。

function Animal(name){
this.name = name;
}
Animal.prototype.say=function(){
console.log('I am ' + this.name);
}

function Cat(){}
Cat.prototype = new Animal();

var cat = new Cat();
cat.say();

将Cat的prototype属性设为一个Animal对象,此时Cat可以继承Animal的属性。

当读取对象的某个属性时,JavaScript引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找。如果直到最顶层的Object.prototype还是找不到,则返回undefined。

但上面的继承方法也有缺陷,Cat构造函数传递参数,此时可以使用apply或call的方法。

function Cat(name, age){
Animal.call(this,name);
this.age = age;
}
Cat.prototype = new Animal();
Cat.prototype.constructor=Cat;

Cat.prototype.say = function(){
Animal.prototype.say.call(this,null);
console.log('I am ' + this.age + ' years old');
}

var cat = new Cat('Tom',15);
cat.say();

//I am Tom
//I am 15years old

instanceof

instanceof 云悬浮用于检测对象是否属于某个类

//true
cat instanceof Animal

实际上instanceof运算符并不会检测cat是否由Animal()构造函数初始化而来,而会检测cat是否继承自Animal.prototype。

实际上,instanceof判断的是一个对象原型链上的__proto__与另一个构造函数的prototype是否相等

cat.__proto__ == Cat.prototype      //true
cat instanceof Cat //true

cat.__proto__.__proto__ == Animal.prototype //true
cat instanceof Animal //true

cat.__proto__={} //改变cat对象的__proto__属性
cat instanceof Cat //输出false