在 Javascript 中向自定义对象添加方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6276175/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 20:08:01  来源:igfitidea点击:

Adding methods to custom objects in Javascript

javascriptprototype-programming

提问by aditya_gaur

Possible Duplicate:
Use of 'prototype' vs. 'this' in Javascript?

可能的重复:
在 Javascript 中使用“原型”与“这个”?

I went to various websites but not able to understand the difference between the following ways of adding methods to custom objects:

我访问了各种网站,但无法理解以下向自定义对象添加方法的方法之间的区别:

Method 1:

方法一:

function circle(radius){
     this.radius = radius;
     this.area = function(){ return 3.14*this.radius*this.radius;}
}

Method 2:

方法二:

function circle(radius){
     this.radius = radius;
}
circle.prototype.area = function(){ return 3.14*this.radius*this.radius; }

Are there any performance or design issues that one of the methods has and the other does not?

是否存在其中一种方法存在而另一种方法不存在的任何性能或设计问题?

采纳答案by Wladimir Palant

Here is one way to see the difference:

这是查看差异的一种方法:

var circle1 = circle(1);
var circle2 = circle(1);
alert(circle1.area == circle2.area);

For Method1 you will see falsewhile Method2 yields in true. That's because in the first case you assign a new closure function to each object created, two objects end up with different areafunctions even though both do the same thing. In the second case the objects share the same prototype object with its areamethod, that method is of course identical in both cases.

对于 Method1,您将看到 Method2falsetrue. 这是因为在第一种情况下,您为每个创建的对象分配了一个新的闭包函数,area即使两个对象都做同样的事情,但最终会得到不同的函数。在第二种情况下,对象与其area方法共享相同的原型对象,该方法在两种情况下当然是相同的。

Usually Method2 is preferable for several reasons:

通常方法 2 是可取的,原因有以下几个:

  1. Object creation is faster because only custom properties need to be initialized.
  2. You don't waste memory on instantiating multiple copies of the same thing.
  3. You can easily find out which of the object properties have custom values by calling Object.hasOwnProperty.
  1. 对象创建速度更快,因为只需要初始化自定义属性。
  2. 您不会在实例化同一事物的多个副本上浪费内存。
  3. 您可以通过调用 轻松找出哪些对象属性具有自定义值Object.hasOwnProperty

There are some disadvantages as well to keep in mind.

还有一些缺点需要记住。

  1. You always spend time on setting up the prototype even if you never create any objects.
  2. Property access is slightly slower because the JavaScript engine needs to check object properties first and then the properties of the prototype object (modern JavaScript engines optimize this pretty well however).
  3. There is a common fall trap of putting objects or arrays on the prototype, these will be shared between all object instances.
  1. 即使您从未创建任何对象,您也总是花时间设置原型。
  2. 属性访问速度稍慢,因为 JavaScript 引擎需要先检查对象属性,然后再检查原型对象的属性(然而现代 JavaScript 引擎对此进行了很好的优化)。
  3. 将对象或数组放在原型上有一个常见的陷阱,这些将在所有对象实例之间共享。

Here is an example of the common mistake:

以下是常见错误的示例:

function NumberCollection()
{
}
NumberCollection.prototype = {
    numbers: [],
    sum: function()
    {
        var result = 0;
        for (var i = 0; i < this.numbers.length; i++)
            result += this.numbers[i];
        return result;
    }
}

var c1 = new NumberCollection();
c1.numbers.push(5);
alert(c1.sum());   // Shows 5
var c2 = new NumberCollection();
c2.numbers.push(6);
alert(c2.sum());   // Oops, shows 11 because c1.numbers and c2.numbers is the same

The correct approach here would be:

这里的正确方法是:

function NumberCollection()
{
    this.numbers = [];
}
NumberCollection.prototype = {
    numbers: null,
    sum: function()
    {
        var result = 0;
        for (var i = 0; i < this.numbers.length; i++)
            result += this.numbers[i];
        return result;
    }
}

回答by Tomalak

The first method (let's call it type 1) adds the area()function to the object itself. Every time you construct a circleobject with new, its body will be copied(!) to the new instance.

第一个方法(我们称之为类型 1)将area()函数添加到对象本身。每次使用 构造circle对象时new,其主体都会被复制(!) 到新实例。

The second method (type 2) adds the area()function to the object prototype (the prototype is "one level up" in the hierarchy). Every time you create a new instance of circleonly the radiusproperty will be copied.

第二种方法(类型 2)将area()函数添加到对象原型(原型是层次结构中的“上一级”)。每次创建新实例时,circle只会radius复制该属性。

Now when you call area()on an instance of the second object, JavaScript cannot find that function on the object itself. Now it "goes up" the prototype chain and uses the first function of that name it finds.

现在,当您调用area()第二个对象的实例时,JavaScript 无法在对象本身上找到该函数。现在它“上升”到原型链并使用它找到的那个名字的第一个函数。

Now this has several implications:

现在这有几个含义:

  1. New objects instances will be smaller (less physical code)
  2. You can change the implementation of areafor all existing objects of type 2 at onceand while they live (by changing the prototype), you can't do that for type 1
  3. You can override the functionality of areain a single instance of type 2 while keeping the "original implementation" of the function around
  1. 新对象实例会更小(物理代码更少)
  2. 您可以更改实施area2类型的所有现有对象一次,虽然他们生活(通过改变原型),你不能这样做,对于1型
  3. 您可以覆盖area类型 2 的单个实例中的功能,同时保留函数的“原始实现”