Javascript 何时使用原型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4736910/
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
Javascript when to use prototypes
提问by opl
I'd like to understand when it is appropriate to use prototype methods in js. Should they always be used? Or are there cases where using them is not preferred and/or incurs a performance penalty?
我想了解什么时候在 js 中使用原型方法是合适的。是否应该始终使用它们?或者是否存在不推荐使用它们和/或导致性能损失的情况?
In searching around this site on common methods for namespacing in js, it seems that most use a non-prototype based implementation: simply using an object or a function object to encapsulate a namespace.
在本网站上搜索 js 中命名空间的常用方法时,似乎大多数使用非基于原型的实现:简单地使用对象或函数对象来封装命名空间。
Coming from a class-based language, it's hard not to try and draw parallels and think that prototypes are like "classes" and the namespace implementations I mentioned are like static methods.
来自基于类的语言,很难不尝试绘制相似之处并认为原型就像“类”,而我提到的命名空间实现就像静态方法。
回答by Daniel Earwicker
Prototypes are an optimisation.
原型是一种优化。
A great example of using them well is the jQuery library. Every time you obtain a jQuery object by using $('.someClass')
, that object has dozens of "methods". The library could achieve that by returning an object:
很好地使用它们的一个很好的例子是 jQuery 库。每次使用 获取 jQuery 对象时$('.someClass')
,该对象都有数十种“方法”。库可以通过返回一个对象来实现:
return {
show: function() { ... },
hide: function() { ... },
css: function() { ... },
animate: function() { ... },
// etc...
};
But that would mean that every jQuery object in memory would have dozens of named slots containing the same methods, over and over.
但这意味着内存中的每个 jQuery 对象都会有几十个包含相同方法的命名槽,一遍又一遍。
Instead, those methods are defined on a prototype and all jQuery objects "inherit" that prototype so as to gain all those methods at very little runtime cost.
相反,这些方法是在原型上定义的,并且所有 jQuery 对象“继承”该原型,以便以极少的运行时成本获得所有这些方法。
One vitally important part of how jQuery gets it right is that this is hidden from the programmer. It's treated purely an optimisation, not as something that you have to worry about when using the library.
jQuery 如何做到这一点的一个至关重要的部分是,这是对程序员隐藏的。它被视为纯粹的优化,而不是您在使用库时必须担心的事情。
The problem with JavaScript is that naked constructor functions require the caller to remember to prefix them with new
or otherwise they typically don't work. There is no good reason for this. jQuery gets it right by hiding that nonsense behind an ordinary function, $
, so you don't have to care how the objects are implemented.
JavaScript 的问题在于裸构造函数要求调用者记住给它们加上前缀,new
否则它们通常不起作用。这没有充分的理由。jQuery 通过将这些废话隐藏在一个普通函数后面$
,从而做到了正确,因此您不必关心对象是如何实现的。
So that you can conveniently create an object with a specified prototype, ECMAScript 5 includes a standard function Object.create
. A greatly simplified version of it would look like this:
为了方便地创建具有指定原型的对象,ECMAScript 5 包含一个标准函数Object.create
。它的一个大大简化的版本如下所示:
Object.create = function(prototype) {
var Type = function () {};
Type.prototype = prototype;
return new Type();
};
It just takes care of the pain of writing a constructor function and then calling it with new
.
它只是解决了编写构造函数然后用new
.
When would you avoid prototypes?
你什么时候会避免原型?
A useful comparison is with popular OO languages such as Java and C#. These support two kinds of inheritance:
一个有用的比较是与流行的 OO 语言,如 Java 和 C#。这些支持两种继承:
- interfaceinheritance, where you
implement
aninterface
such that the class provides its own unique implementation for every member of the interface. - implementationinheritance, where you
extend
aclass
that provides default implementations of some methods.
- 接口继承,在那里你
implement
一个interface
这样的类提供了自己独特的实施接口的每一个成员。 - 实现继承,您可以
extend
在class
其中提供某些方法的默认实现。
In JavaScript, prototypical inheritance is a kind of implementationinheritance. So in those situations where (in C# or Java) you would have derived from a base class to gain default behaviour, which you then make small modifications to via overrides, then in JavaScript, prototypical inheritance makes sense.
在 JavaScript 中,原型继承是一种实现继承。因此,在那些情况下(在 C# 或 Java 中)您将从基类派生以获得默认行为,然后您通过覆盖对其进行小的修改,然后在 JavaScript 中,原型继承是有意义的。
However, if you're in a situation where you would have used interfaces in C# or Java, then you don't need any particular language feature in JavaScript. There is no need to explicitly declare something that represents the interface, and no need to mark objects as "implementing" that interface:
但是,如果您在使用 C# 或 Java 中的接口的情况下,那么您不需要 JavaScript 中的任何特定语言功能。不需要显式声明表示接口的东西,也不需要将对象标记为“实现”该接口:
var duck = {
quack: function() { ... }
};
duck.quack(); // we're satisfied it's a duck!
In other words, if each "type" of object has its own definitions of the "methods", then there is no value in inheriting from a prototype. After that, it depends on how many instances you allocate of each type. But in many modular designs, there is only one instance of a given type.
换句话说,如果每个“类型”的对象都有自己的“方法”定义,那么从原型继承就没有价值。之后,这取决于您为每种类型分配了多少实例。但是在许多模块化设计中,给定类型只有一个实例。
And in fact, it has been suggested by many people that implementation inheritance is evil. That is, if there are some common operations for a type, then maybe it's clearer if they are not put into a base/super class, but are instead just exposed as ordinary functions in some module, to which you pass the object(s) you want them to operate on.
事实上,很多人都认为实现继承是邪恶的。也就是说,如果某个类型有一些常见的操作,那么如果它们不放入基类/超类中,而只是作为某个模块中的普通函数公开,您将对象传递给该模块,则可能会更清楚您希望他们进行操作。
回答by KeatsKelleher
You should use prototypes if you wish to declare a "non-static" method of the object.
如果您希望声明对象的“非静态”方法,则应使用原型。
var myObject = function () {
};
myObject.prototype.getA = function (){
alert("A");
};
myObject.getB = function (){
alert("B");
};
myObject.getB(); // This works fine
myObject.getA(); // Error!
var myPrototypeCopy = new myObject();
myPrototypeCopy.getA(); // This works, too.
回答by hellatan
One reason to use the built-in prototype
object is if you'll be duplicating an object multiple times that will share common functionality. By attaching methods to the prototype, you can save on duplicating methods being created per each new
instance. But when you attach a method to the prototype
, all instances will have access to those methods.
使用内置prototype
对象的一个原因是,如果您要多次复制一个共享公共功能的对象。通过将方法附加到原型,您可以节省为每个new
实例创建的重复方法。但是,当您将方法附加到 时prototype
,所有实例都可以访问这些方法。
Say you have a base Car()
class/object.
假设您有一个基Car()
类/对象。
function Car() {
// do some car stuff
}
then you create multiple Car()
instances.
然后创建多个Car()
实例。
var volvo = new Car(),
saab = new Car();
Now, you know each car will need to drive, turn on, etc. Instead of attaching a method directly to the Car()
class (which takes up memory per each instance created), you can attach the methods to the prototype instead (creating the methods only once), therefore giving access to those methods to both the new volvo
and saab
.
现在,您知道每辆车都需要行驶、启动等。而不是将方法直接附加到Car()
类(每个创建的实例都占用内存),您可以将方法附加到原型(仅创建方法)一次),因此可以访问这些方法给 newvolvo
和saab
.
// just mapping for less typing
Car.fn = Car.prototype;
Car.fn.drive = function () {
console.log("they see me rollin'");
};
Car.fn.honk = function () {
console.log("HONK!!!");
}
volvo.honk();
// => HONK!!!
saab.drive();
// => they see me rollin'
回答by Pointy
Put functions on a prototype object when you're going to create lots of copies of a particular kind of object and they all need to share common behaviors. By doing so, you'll save some memory by having just one copy of each function, but that's only the simplest benefit.
当您要为特定类型的对象创建大量副本并且它们都需要共享共同行为时,请将函数放在原型对象上。通过这样做,您可以通过每个函数的一个副本来节省一些内存,但这只是最简单的好处。
Changing methods on prototype objects, or adding methods, instantly changes the nature of all the instances of the corresponding type(s).
更改原型对象上的方法或添加方法,会立即更改相应类型的所有实例的性质。
Now exactly whyyou'd do all these things is mostly a function of your own application design, and the kinds of things you need to do in client-side code. (A whole different story would be code inside a server; much easier to imagine doing more large-scale "OO" code there.)
现在,您为什么要做所有这些事情主要是您自己的应用程序设计的一个功能,以及您需要在客户端代码中做的事情。(一个完全不同的故事是服务器内的代码;更容易想象在那里做更多大规模的“OO”代码。)
回答by Anil Namde
If i explain in class based term then Person is class, walk() is Prototype method. So walk() will have its existence only after you instantiate new object with this.
如果我用基于类的术语来解释,那么 Person 是类,walk() 是 Prototype 方法。所以 walk() 只有在你用 this 实例化新对象后才会存在。
So if you want to create the copies of object like Person u can create many users Prototype is good solution as it saves memory by sharing/inheriting same copy of function for each of the object in memory.
因此,如果您想创建像 Person 这样的对象副本,您可以创建许多用户,Prototype 是一个很好的解决方案,因为它通过为内存中的每个对象共享/继承相同的函数副本来节省内存。
Whereas static is not that great help in such scenario.
而静态在这种情况下并没有那么大的帮助。
function Person(){
this.name = "anonymous";
}
// its instance method and can access objects data data
Person.prototype.walk = function(){
alert("person has started walking.");
}
// its like static method
Person.ProcessPerson = function(Person p){
alert("Persons name is = " + p.name);
}
var userOne = new Person();
var userTwo = new Person();
//Call instance methods
userOne.walk();
//Call static methods
Person.ProcessPerson(userTwo);
So with this its more like instance method. The object's approach is like Static methods.
因此,它更像是实例方法。对象的方法类似于静态方法。
https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript
https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript