简体   繁体   English

JavaScript中的原型

[英]Prototypes in JavaScript

In the JavaScript the same thing you can do in many different ways. 在JavaScript中你可以用许多不同的方式做同样的事情。

Consider the examples: 考虑一下例子:

1: 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: 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());

The second is better than first because we dont define the same function area for any instance of the Circle . 第二个比第一个好,因为我们没有为Circle的任何实例定义相同的功能区域

But lets consider 3: 但让我们考虑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());

Is there any reason to prefer second style instead of third? 有没有理由更喜欢第二种风格而不是第三种? Or I misunderstood something at all? 或者我误解了一些东西?

I would definitely go with example 2. Neither example 1 or 3 make good use of JavaScript's object-oriented features because: 我肯定会使用示例2.示例1或3都不能充分利用JavaScript的面向对象功能,因为:

  1. You duplicate method definitions in each instance. 您在每个实例中复制方法定义。
  2. By returning a new object instead of using this , you lose the identity of the class, ie you can no longer do checks like a instanceof Circle . 通过返回一个新对象而不是使用this ,您将失去该类的标识,即您不能再像a instanceof Circle那样进行检查。
  3. You give up the possibility of inheritance since you do not use prototypes. 您放弃了继承的可能性,因为您不使用原型。

Is there any reason to prefer second style instead of third? 有没有理由更喜欢第二种风格而不是第三种?

The third style is still wasting a small amount of space in order to store the association between the name area and the area function. 第三款式还是浪费,以便存储名称之间的关联的少量空间area和区域功能。

Also because you are returning a new Object from the {...} literal, instanceof Circle won't work. 另外,因为您从{...}文字返回一个新Object ,所以instanceof Circle不起作用。

The second is better than first because we dont define the same function area for any instance of the Circle. 第二个比第一个好,因为我们没有为Circle的任何实例定义相同的功能区域。

Indeed, but it can sometimes be useful to define a new copy of each method—a copy that, thanks to closures, can know what object it is bound to. 确实,但有时定义每个方法的新副本有用 - 一个副本,由于闭包,可以知道它绑定到哪个对象。 With traditional prototyping you only get the this context which is set from the object the caller retrieved it from, rather than bound to a particular object. 使用传统的原型设计,您只能获得this上下文, this上下文是从调用者从中检索它的对象设置的,而不是绑定到特定对象。 The first way avoids the problems of this -retention in things like event handlers, at the price of some loss of efficiency. 第一种方法避免了诸如事件处理程序之类的this保留问题,其代价是效率降低。

The difference between Circle.prototype.area and Circle.area is that one is only accessible with a instance of the class. Circle.prototype.areaCircle.area之间的区别在于只能通过类的实例访问。

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

and

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

The problem with example 2 is, that when you accidentally forget to use the new operator when creating the object, and just call var a = Circle(10); 示例2的问题是,当您在创建对象时意外忘记使用new运算符时,只需调用var a = Circle(10); (which is fine for the 3rd example, but not for the 2nd), then your constructor creates big trouble: (这对于第3个例子来说很好,但对于第2个例子没有问题),那么你的构造函数会造成很大的麻烦:

this.r = radius;

Since you didn't use new , this will be assigned the global object, so the constructor really sets the global variable r ! 由于您没有使用newthis将为其分配全局对象,因此构造函数确实设置了全局变量r

So I would strongly prefer example 3. 所以我非常喜欢例子3。

I'd like to comment on "The second is better than first because we dont define the same function area for any instance of the Circle." 我想评论“第二个比第一个更好,因为我们没有为Circle的任何实例定义相同的功能区域。” In practice, this may be such a negligable advantage as to be totally insignificant. 在实践中,这可能是一个可以忽略不计的优点,完全无关紧要。 I tend to favor syntax and human-friendly code over efficiency, unless performance is noticably affected . 除非性能受到显着影响否则我倾向于支持语法和人性化代码而不是效率。 I've been completely ignoring the Prototype feature of javascript and also avoiding the use of "this", basically using technique #1. 我完全忽略了javascript的Prototype功能,也避免使用“this”,基本上使用了#1技术。 It's working just fine for me. 它对我来说很好。 I find avoiding "this" prevents a lot of confusion about just what "this" refers to. 我发现避免“这个”可以防止对“这个”所指的内容产生很多疑惑。 It's perfectly possible to create inheritance-type structures without "prototype". 完全可以创建没有“原型”的继承类型结构。 You simple create a superclass object, and override whichever methods you want. 您可以简单地创建一个超类对象,并覆盖您想要的任何方法。 Douglas Crockford has written pretty extensively on numerous different ways to do inheritance in javascript. 道格拉斯·克罗克福德(Douglas Crockford)已经在javascript中以无数种不同的方式编写了继承。

I will agree with casablanca above that being able to test for type using "instanceof" is a nice advantage of returning "this". 我同意上面的卡萨布兰卡,能够使用“instanceof”测试类型是返回“this”的一个很好的优势。 Perhaps I'll take another look at "protype" and "this" on a future project. 也许我会在未来的项目中再看看“protype”和“this”。 For now, though, I'm getting along just fine without them. 但就目前而言,如果没有他们,我相处得很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM