JavaScript中对象的定义和继承的几种方式
前几天看张龙老师讲的JavaScript视频的时候,觉得老师讲的很好,继承和定义对象这很有意思,又查了几本书和一些资料,也慢慢的记住了这几种对象的定义方式和继承,但是日后,我可能会忘,所以写成博客和大家分享一下,并且做一下总结,我本来想看一看javascript高级程序设计这本书是怎么说的,可以图书馆刚上一天这书,就被人给借走了,只好等他换回去我在看了,我会慢慢的对这篇文章进行扩充。
定义对象的几种方式:
1)基于已有对象的扩充其属性和方法
这种方式是创建一个自定义对象的最简单方式,然后可以为他添加属性和方法,如下所示
2)通过工厂方式
工厂模式是软件工程领域一种广为人知的模式,这种模式抽象了创建具体对象的过程,通过一种函数,用函数来封装以特定接口创建对象的细节。工厂方式的特点是通过特定的工厂方法创建特定类型的对象。以下是比较典型的实现代码。
接下来给它加上参数
也可以让一个函数对象被多个对象所共享,而不是每一个对象拥有一个函数对象
3)构造函数方式
构造函数的方式和工厂方式很像,通过构造函数的方式可以创建特定的对象,像Object和Array这样的原生构造函数,在运行时会自动出现在执行环境中,通过创建自定义的构造函数,从而自定义对象类型的属性和方法。
用的更多的是给他传递参数
用构造函数的方式,按照惯例通长首字母大写,如Person中的P,而不是以一个小写的字母开头,这个做法鉴于其他OO语言,主要是为了区别。
构造函数方式和工厂方式都有一个不可忽略的弊端,就是每个对象被实例化时,都会实例化类中的方法,而这个弊端会造成每个对象都有独立的版本。
4)原型(“prototype”)方式
通过原型的方式我们可以避免这种弊端。我们创建的每个函数都有一个prototype属性,这个属性就是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法。
对于原型方式来说,如果使用原型对象,那么生成的所有对象会共享原型中的属性,这样一个对象改变了该属性也会反映到其他对象中。
单纯的使用原型方式定义对象无法再构造函数中为属性赋初值,只能在对象生成后再去改变属性值。
5)混合方式(原型+构造函数)
工厂方式、构造方式、原型方式都有一些缺陷,那种方式可以很好的实现对象的创建呢?使用原型+构造函数方式来定义对象,对象之间的属性互不干扰,各个对象间共享同一个方法。通过构造函数方式定义对象的所有非函数属性,用原型方式定义对象的函数属性,所有的属性都是单一对象私有的,而方法则是所有对象公有的。如下所示:
6)通过动态原型方式
对于习惯了使用Java的人来说,面向对象的“封装”特征并没有体现在上述的代码中,混合方式并没有对对象的属性和方法进行严密封装。在JavaScript中,提供了一种动态原型的方式对对象的属性和方法进行严密的封装,在构造函数中通过一个 标志量让所有对象共享一个方法,而每个对象拥有自己的属性。
JavaScript中的继承
和定义对象一样,在JavaScript中实现继承也有多种方式,javascript是弱类型的语言,有很多的地方没有明确的限制,挺多的时候都掌握在我们的手中。我们可以根据自己的方式来进行各种操作。
1)对象的冒充
使用对象的冒充的时候,必须使用构造函数,否则无法实现继承
使用对象冒充的方式,可以实现多继承,让一个子类有多个父类,与单一的继承方式一样。
2)通过call方法
在Function对象中有两个方法可以实现继承,即call方法和apply方法。也正是因为这个我们所定义的每个函数都有call方法,我们可以通过函数名调用call方法,对于call方法的参数列表来说并不固定,根据实际的情况增加和减少。第一个参数是指调用当前的Function对象,并将它传递给函数中的this,而剩下的所有参数都是当前函数的参数。逐一赋值给函数中的参数。如下代码所示:
3)通过apply方法
apply方法也是Function对象里的方法,使用和call方法基本一致。唯一的区别就是apply方法的参数,call的方法的参数是不固定的,apply方法的参数只有两个,第一个是调用当前的Function对象,即this对象,第二个是传入参数的数组。如代码所示:
4)原型链的方式
在之前的定义对象的时候使用了使用原型的方式创建对象,也可以通过原型的方式进行对象的继承。通常称作原型链。但是这种方式无法给构造函数传递参数。如代码所示:
5)混合方式
在JavaScript中最好的方式就是用混合方式实现对象间的继承。和定义对象一样,我们可以将属性和方法用不同的方式定义,用call或apply方式定义继承对象的属性,利用原型链的方式实现方法的继承。如下代码所示:
以上的总结仅仅是我简单的总结,等日后学的比较深了会在扩充一下,希望大家理解一下。