JavaScript中的原型

时间:2010-08-28 20:31:53

标签: javascript oop

在JavaScript中你可以通过许多不同的方式做同样的事情。

考虑以下示例:

1:

function Circle(radius) {
 return {
  "r" : radius,
  "area" : function(){
   return Circle.pi * this.r * this.r; 
  }
 }
}
Circle.pi = 3.14159;

var a = Circle(10);
alert(a.area());

2:

function Circle(radius) {
    this.r = radius;
}

Circle.pi = 3.14159;
Circle.prototype.area = function(){
 return Circle.pi * this.r * this.r; 
}

var a = new Circle(10);
alert(a.area());

第二个比第一个好,因为我们没有为 Circle 的任何实例定义相同的函数 area

但我们考虑一下 3:

function Circle(radius) {
 return {
  "r" : radius,
  "area" : Circle.area
 }
}
Circle.pi = 3.14159;
Circle.area = function(){
 return Circle.pi * this.r * this.r; 
}

var a = Circle(10);
alert(a.area());

有没有理由更喜欢第二种风格而不是第三种?或者我误解了一些东西?

5 个答案:

答案 0 :(得分:4)

我肯定会使用示例2.示例1或3都没有充分利用JavaScript的面向对象功能,因为:

  1. 您在每个实例中复制方法定义。
  2. 通过返回新对象而不是使用this,您将失去该类的身份,即您无法再执行a instanceof Circle之类的检查。
  3. 由于不使用原型,您放弃了继承的可能性。

答案 1 :(得分:2)

  

有没有理由更喜欢第二种风格而不是第三种?

第三种风格仍在浪费空间,以便存储名称area和区域功能之间的关联。

另外,因为您从Object字面值返回新的{...}instanceof Circle将无效。

  

第二个比第一个好,因为我们没有为Circle的任何实例定义相同的功能区域。

确实,但有时可用于定义每个方法的新副本 - 一个副本,由于闭包,可以知道它绑定到哪个对象。使用传统的原型设计,您只能获得从调用者从中检索的对象设置的this上下文,而不是绑定到特定对象。第一种方法避免了this的问题 - 保留事件处理程序之类的东西,代价是效率降低。

答案 2 :(得分:1)

Circle.prototype.areaCircle.area之间的区别在于只能通过类的实例访问。

Circle.prototype.area = function(){};
Circle.area // wrong
(new Circle()).area // ok (you need a Circle object)

Circle.area = function(){};
Circle.area // ok (you don't need the object, its static)
(new Circle()).area // wrong

答案 3 :(得分:0)

示例2的问题是,当您在创建对象时意外忘记使用new运算符,并且只需调用var a = Circle(10);(这对第3个示例很好,但对于2),那么你的构造函数会造成很大的麻烦:

this.r = radius;

由于你没有使用newthis将被赋予全局对象,因此构造函数确实设置了全局变量r

所以我非常喜欢示例3。

答案 4 :(得分:0)

我想评论“第二个比第一个好,因为我们没有为Circle的任何实例定义相同的功能区域。”在实践中,这可能是一个可以忽略不计的优点,完全无关紧要。我倾向于支持语法和人性化代码而非效率,除非性能受到显着影响。我完全忽略了javascript的Prototype功能,也避免使用“this”,基本上使用了#1技术。它对我来说很好。我发现避免“这个”可以防止对“这个”所指的内容产生很多疑惑。完全可以创建没有“原型”的继承类型结构。您可以简单地创建一个超类对象,并覆盖您想要的任何方法。道格拉斯·克罗克福德(Douglas Crockford)已经在javascript中以无数种不同的方式编写了继承。

我同意上面的卡萨布兰卡,能够使用“instanceof”测试类型是返回“this”的一个很好的优势。也许我会在未来的项目中再看看“protype”和“this”。但就目前而言,如果没有他们,我相处得很好。