前端之家收集整理的这篇文章主要介绍了
详解JavaScript基于面向对象之创建对象(2),
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
接着上文《详解JavaScript基于面向对象之创建对象(1)》继续学习。
4、原型方式
我们创建的每个函数都有一个通过prototype(原型)属性,这个属性是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法。逻辑上可以这么理解:prototypt通过条用构造函数而创建的那个对象的原型对象。使用原型的好处就是可以让所有对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中定义对象信息,而是直接将这些信息添加到原型中。
原型方式利用了对象的prototype 属性,可以把它看成创建新对象所依赖的原型。这里,首先用空构造函数来设置函数名。然后所有的属性和方法都被直接赋予prototype属性。我重写了前面的例子,代码如下:
属性的
方法都赋予prototype
属性
Car.prototype.color = "blue";
Car.prototype.doors = 4;
Car.prototype.mpg = 25;
Car.prototype.showColor = function() {
return this.color;
};
var Car1 = new Car();
var Car2 = new Car();
document.write(Car1.showColor()+"
");//
输出:blue
document.write(Car2.showColor());//
输出:blue
在这段代码中,首先定义构造函数Car(),其中无任何代码。接下来的几行代码,通过给Car的 prototype 属性添加属性去定义Car对象的属性。调用new Car()时,原型的所有属性都被立即赋予要创建的对象,意味着所有Car实例存放的都是指向 showColor() 函数的指针。从语义上讲,所有属性看起来都属于一个对象,因此解决了前面的工厂方式和构造函数方式存在的问题。
此外,使用这种方式,还能用 instanceof 运算符检查给定变量指向的对象的类型:
输出:true
原型方式看起来是个不错的
解决方案。遗憾的是,它并不尽如人意。首先,这个构造
函数没有参数。使用原型方式,不能通过给构造
函数传递参数来初始化
属性的值,因为Car1和Car2的color
属性都等于 "blue",doors
属性都等于4,mpg
属性都等于25。这意味着必须在
对象创建后才能改变
属性的默认值,这点很令人讨厌,但还没完。真正的问题出现在
属性指向的是对象,而不是
函数时。
函数共享不会造成问题,但对象却很少被多个实例共享。请思考下面的例子:
函数,且不能传递参数
Car.prototype.color = "blue";
Car.prototype.doors = 4;
Car.prototype.mpg = 25;
Car.prototype.drivers = new Array("Mike","John");
Car.prototype.showColor = function() {
return this.color;
};
var Car1 = new Car();
var Car2 = new Car();
Car1.drivers.push("Bill");
document.write(Car1.drivers+"
");//
输出:Mike,John,Bill
document.write(Car2.drivers);//
输出 :Mike,Bill
上面的代码中,属性drivers是指向Array对象的指针,该数组中包含两个名"Mike"和 "John"。由于 drivers是引用值,Car的两个实例都指向同一个数组。这意味着给Car1.drivers添加值 "Bill",在 Car2.drivers 中也能看到。输出这两个指针中的任何一个,结果都是显示字符串 "Mike,Bill"。由于创建对象时有这么多问题,你一定会想,是否有种合理的创建对象的方法呢?答案是有,需要联合使用构造函数和原型方式。
5、混合的构造函数/原型方式(推荐使用)
混合使用构造函数方式和原型方式,就可像用其他程序设计语言一样创建对象。这种概念非常简单,即用构造函数定义对象的所有非函数属性,用原型方式定义对象的函数属性(方法)。结果是,所有函数都只创建一次,而每个对象都具有自己的对象属性实例。我们重写了前面的例子,代码如下:
");//
输出:Mike,Bill
documnet.write(Car2.drivers);//
输出:Mike,John
添加
方法
if (typeof Car._initialized == "undefined") {
Car.prototype.showColor = function() {
return this.color;
};
Car._initialized = true; //设置为true,不必再为prototype
添加方法
}
}
var Car1 = new Car("red",23);//
生成一个Car对象
var Car2 = new Car("blue",25);
Car1.drivers.push("Bill");//向Car1对象实例的drivers
属性添加一个元素
document.write(Car1.drivers+"
");//
输出:Mike,Bill
document.write(Car2.drivers);//
输出:Mike,John