之所以给“类”加上引号,是因为书上说JavaScript中其实没有类这么个概念。
注:文中代码及一些文字摘自《JavaScript高级程序设计》,有些地方稍有修改。
1、工厂方式:
function createCar(sColor, iDoors, iMpg){
var oTempCar = new Object
oTempCar.color = sColor
oTempCar.doors = iDoors
oTempCar.mpg = iMpg
oTempCar.showColor = function(){
alert(this.color)
}
return oTempCar
}
书上说,这种方式有人反对,原因有2:首先是语义上的原因,它看起来不像使用带有构造函数的new运算符那么正规。第二是功能上的原因,以上代码每创建一个Car时,都要创建一个新的function:showColor。
var car1 = createCar("red", 2, 23)
var car2 = createCar("blue", 4, 30)
alert(car1.showColor==car2.showColor) //显示“false”,表示这2个function不是同一个实例。
第二个问题有个解决办法,就是把showColor这个function定义在工厂函数createCar的外面,然后在createCar里面给oTempCar添加一个showColor属性,指向外面的showColor函数。但这种方式不太好,理由是:该函数看起来不像对象的方法。
2、构造函数方式:
function Car(sColor, iDoors, iMpg){
this.color = sColor
this.doors = iDoors
this.mpg = iMpg
this.showColor = function(){
alert(this.color)
}
}
这种方式通过new运算符调用Car这个构造函数,构造之前会先隐式的创建一个对象,只有用this才能访问这个对象,然后可以直接给this添加属性并赋值,构造函数默认返回这个被新建出来的对象,不用显式使用return。
但以上方式和工厂方式存在同样的一个问题:每创建一个Car时,都要创建一个新的function:showColor。当然也可以用上面提到的方法解决。
3、原型方式
function Car(){
}
Car.prototype.color = "red"
Car.prototype.doors = 4
Car.prototype.mpg = 23
Car.prototype.showColor = function(){
alert(this.color)
}
prototype就是所谓的原型,可以看作是一个模板吧,对象的模板,跟“类”的概念差不多。这里解决了前面2种方式的问题,但新的问题随之而来:首先这种方式不能给构造函数传递参数,必须给属性一个一个的赋值,否则得到的对象都是一样的。还有个更糟糕的问题是,假如某个属性指向一个对象,那么这个属性将被所有对象共享:
function Car(){
}
Car.prototype.color = "red"
Car.prototype.doors = 4
Car.prototype.mpg = 23
Car.prototype.drivers = new Array("Mike", "Sue");
Car.prototype.showColor = function(){
alert(this.color)
}
var car1 = new Car
var car2 = new Car
car1.drivers.push("Matt")
alert(car2.drivers)
如上,给car1添加了一个driver,car2中也多出了这么个driver,这是个大问题。
原因在于:给prototype添加的属性是一个对象,构造Car时便会把这个对象的引用复制给每个car。而之前的构造函数方式不存在这种问题,是因为构造函数是在每次创建对象时单独给每个添加属性,而不是一开始在prototyp这样的“对象模板”中写死了。
4、混合方式(构造函数&原型)
很明显,解决以上所有问题的方法产生了:把构造函数方式和原型方式混合,取长补短。
既然方法必须共享,那么就采用原型方式定义方法;既然属性不能共享,那么就采用构造函数方式定义属性。Perfect!
function Car(sColor, iDoors, iMpg){
this.color = sColor
this.doors = iDoors
this.mpg = iMpg
this.drivers = new Array("Mike", "Sue")
}
Car.prototype.showColor = function(){
alert(this.color)
}
不过仍有些开发者觉得这种方法不够perfect。
5、动态原型方式
有开发者认为,在构造函数内部找属性,在外部找方法的做法不合逻辑,因此他们设计出了动态原型方式,这种方式把对象的方法给定义到了构造函数内部,但是是在内部使用prototype定义方法。由于构造函数本身在每构造一个对象时都会执行一次,所以对象的方法会在每构造一次时重新创建,覆盖掉之前的方法。为了防止每次都给prototype创建新的function,可以给Car这个对象(Car本身也是个对象,一个function对象)添加一个标记,用于判断prototype是否被初始化过:
function Car(sColor, iDoors, iMpg){
this.color = sColor
this.doors = iDoors
this.mpg = iMpg
this.drivers = new Array("Mike", "Sue")
if(!Car._initialized){
Car.prototype.showColor = function(){
alert(this.color)
}
Car._initialized = true
}
}
还有第6种方式,不过第6种方式存在着和工厂方式、构造函数方式相同的问题,而且还有第15章才能明白的原因,所以这里不做笔记了,15章再说。
OK,回头看一下,其实我觉得混合方式挺好的,动态原型写起来反倒有些麻烦。嗯,看来我跟大多数人想法一样,书上说使用最广泛的是混合构造函数/原型方式。
这篇笔记是我JavaScript的OOP入门篇。
分享到:
相关推荐
JavaScript定义类的几种方式包括工厂方式、构造函数和原型方式,每种方法都有其特点和适用场景,接下来我们将详细探讨。 工厂方式是最早期的面向对象编程在JavaScript中的实践之一。使用工厂方式定义类,本质上就是...
Javascript对象定义的几种方式
JavaScript中定义类或函数,主要有以下几种方式: 1. 工厂方式 工厂方式是JavaScript中创建对象的一种模式,它通过一个工厂函数来封装创建对象的代码。通过工厂函数,我们可以创建多个具有相同属性和方法的对象实例...
在讨论JavaScript中定义对象的几种方式之前,我们先理解一下JavaScript中的对象到底是什么。JavaScript是一种基于原型的编程语言,对象是其核心概念之一。对象可以被视为一个容器,存储各种键值对集合,键为属性名,...
综上所述,在JavaScript中定义类和对象的几种方式各有优劣。直接量方式适用于简单对象的快速定义;工厂方式适用于需要大量重复创建类似对象的场景;而原型方式则提供了代码复用和性能优化的可能性。开发者可以根据...
在JavaScript中实现类的方式主要有几种,包括对象字面量(Object Literal)、构造函数(Constructor)、原型链(Prototype Chain)以及ES6引入的类语法。每种方式都有其适用的场景和特点,理解它们有助于我们更好地...
在JavaScript中,定义类的方法多种多样,这使得开发者可以根据需求选择最合适的方式来创建对象。以下是几种主要的方法: 1. **工厂方式**: 工厂模式是一种创建对象的模式,通过函数来模拟类的概念。在JavaScript...
JavaScript是Web开发中不可或缺的一部分,尤其在前端领域更是发挥着...以上就是JavaScript创建对象的8种常见方式,每种方式都有其适用场景和优缺点。理解并熟练运用这些技巧,可以帮助你在JavaScript开发中游刃有余。
以上就是JavaScript中定义类的几种常见方式,虽然它们没有像其他面向对象语言那样提供显式的`class`关键字,但JavaScript的灵活性使得开发者可以通过这些技巧实现面向对象编程的需求。在实际开发中,随着ES6的引入,...
前言类与实例:类的声明生成实例类与继承:如何实现继承:继承的本质就是原型链继承的几种方式类的定义、实例化类的定义/类的声明方式一:用构造函数模拟类(传统写法)/
在ASP.NET中,我们可以通过以下几种方式使用JavaScript类: 1. **定义和实例化JavaScript对象**:在HTML或者JavaScript代码中,可以定义一个函数构造器,通过new关键字来创建对象实例。例如,定义一个名为Person的...
前言类与实例:类的声明生成实例类与继承:如何实现继承:继承的本质就是原型链继承的几种方式类的定义、实例化类的定义/类的声明方式一:用构造函数模拟类(传统写法)/
以下是对标题和描述中提到的几种JavaScript面向对象编程模式的详细解释: 1. **构造函数与字面量结合模式** 在JavaScript中,我们可以通过构造函数和字面量语法来创建对象。构造函数用于定义对象的类型,而字面量...
函数的定义方式多种多样,每种方式都具有特定的用途和特点。本文将对这些函数定义方式及其区别和使用技巧进行分析。 首先,我们来看第一种也是最常用的函数定义方式——函数声明: ```javascript function func1(...
本文将深入探讨JavaScript中创建对象的几种常见方式以及对象方法。 首先,我们来看“工厂模式”。工厂模式是一种创建对象的抽象方式,通过一个函数来返回一个新的对象。例如: ```javascript function getObj(name...
数组在JavaScript中的定义有多种方式,下面将详细讲解。 1. **隐式创建**: ```javascript var arr1 = [1, 3, 5, 7, 9]; ``` 这种方式直接通过方括号 `[]` 创建数组,并在括号内列出数组的初始元素。 2. **...