[JavaScript] 慎用 somefunction.prototype

在写 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 条评论。

发表评论


注意 - 你可以用以下 HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>