在写 JavaScript 脚本的时候,为了创建一个类,如果不使用框架,一般情况我们都会使用 prototype 来给要创建的类增加公有方法,例如:
- // code from xujiwei.cn
- function Person(name) {
- this.Name = name;
- }
- Person.prototype.SayHello = function() {
- alert('Hello, ' + this.Name);
- }
- Person.prototype.SayBye = function() {
- alert('Goodbye, ' + this.Name);
- }
不过,有的时候,为了书写以及维护的方便,我们会把公有方法的声明写到一个对象里,然后赋值给 Person.prototype,例如:
- // code from xujiwei.cn
- function Person(name) {
- this.Name = name;
- }
- Person.prototype = {
- SayHello: function() {
- alert('Hello, ' + this.Name);
- },
- SayBye: function() {
- alert('Goodbye, ' + this.Name);
- }
- }
使用这种方式,在这个类具有大量公有方法的时候,就不需要维护许多的 Person 标识符,如果某一天这个类的名字需要改变,那么要改的地方只有两个,一个是 function 的声明,一个是 prototype 前面的标识符,如果是使用前一种方式的话,那么有多少个公有方法,就需要维护 N+1 个标识符了,虽然可以使用查找替换,但是从稳定上来说,查找替换可能会引起一些错误,这增加了维护的成本。
这种方式虽然给我们的维护增加了便利,但也引发了另外一个隐藏的问题,就是类的 constructor 属性丢失的问题。
- // code from xujiwei.cn
- function Person1(name) {
- this.Name = name;
- }
- Person1.prototype.SayHello = function() {
- alert('Hello, ' + this.Name);
- }
- Person1.prototype.SayBye = function() {
- alert('Goodbye, ' + this.Name);
- }
- // code from xujiwei.cn
- function Person2(name) {
- this.Name = name;
- }
- Person2.prototype = {
- SayHello: function() {
- alert('Hello, ' + this.Name);
- },
- SayBye: function() {
- alert('Goodbye, ' + this.Name);
- }
- }
- alert(new Person1('Bill').constructor);
- alert(new Person2('Steve').constructor);
运行上面的测试代码我们可以发现,Person1 的 constructor 属性为 Person1 类的构造函数,但是 Person2 的 constructor 属性却是 Object,那么在需要使用 constructor 属性来判断对象类型的时候,就会出现问题。
因此,在写 JavaScript 类的时候,如果不需要使用 constructor 属性来获取对象的类型,那么个人比较倾向于使用第二种写法,但是如果需要使用 constructor 属性以实现自己的反射机制或 GetType 函数等等,那么就要使用第一种写法。
当然,如果在实现自己反射机制或 GetType 函数时并不依赖 constructor 属性,那么两种写法都是可以的了,例如额外维护一个成员变量,用于标识自身的类型等。也可以使用一些现成的JS框架,有一些框架已经实现了JS中类的实现等,例如 js.class,这就看个人需要进行取舍了。
0 条评论。