博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用原型相对于直接在构造函数中定义方法的优势? [重复]
阅读量:2288 次
发布时间:2019-05-09

本文共 6727 字,大约阅读时间需要 22 分钟。

本文翻译自:

This question already has an answer here: 这个问题已经在这里有了答案:

  • 14 answers 14个答案

I am wondering if there are any advantages of using any of these over the other, and which way should I go? 我想知道使用这些方法相对于其他方法是否有任何优势,我应该走哪条路?

Constructor approach: 构造方法:

var Class = function () {    this.calc = function (a, b) {        return a + b;    };};

Prototype approach: 原型方法:

var Class = function () {};Class.prototype.calc = function (a, b) {    return a + b;};

I don't like that, using the prototype, method definitions are separated from the class, and I'm not aware if there is any specific reason I should use this over just the first approach. 我不喜欢这样,使用原型将方法定义与类分开,并且我不知道是否有任何特殊原因我应该仅在第一种方法上使用它。

Also, is there any benefit of using a function literal to define a "class", over just function definition: 此外,与仅使用函数定义相比,使用函数文字来定义“类”有什么好处:

var Class = function () {};

vs VS

function Class () {};

Thanks! 谢谢!


#1楼

参考:


#2楼

First of all you should use the object literal like this: 首先,您应该使用这样的对象文字:

var Class = {  calc: function (a, b) {    return a + b;  }};

This notation is cleaner and also makes it obvious that in Javascript objects are just hashes not something backed from a recipe, like a predefined class. 这种表示法更简洁,也很明显,在Javascript对象中,哈希只是哈希值,而不是预定义类之类的配方支持的东西。

The difference between definitions is that If you add method to prototype there will be only one method created in memory for all instances. 定义之间的区别在于,如果将方法添加到原型,则将在内存中为所有实例创建一个方法。 So if you have a generic method and an object that is created/used in multiple instances you should add the method to prototype. 因此,如果您具有通用方法以及在多个实例中创建/使用的对象,则应将方法添加到原型中。


#3楼

Methods that inherit via the prototype chain can be changed universally for all instances, for example: 通过原型链继承的方法可以针对所有实例进行通用更改,例如:

function Class () {}Class.prototype.calc = function (a, b) {    return a + b;}// Create 2 instances:var ins1 = new Class(),    ins2 = new Class();// Test the calc method:console.log(ins1.calc(1,1), ins2.calc(1,1));// -> 2, 2// Change the prototype methodClass.prototype.calc = function () {    var args = Array.prototype.slice.apply(arguments),        res = 0, c;    while (c = args.shift())        res += c;    return res; }// Test the calc method:console.log(ins1.calc(1,1,1), ins2.calc(1,1,1));// -> 3, 3

Notice how changing the method applied to both instances? 请注意如何更改应用于两个实例的方法? This is because ins1 and ins2 share the same calc() function. 这是因为ins1ins2共享相同的calc()函数。 In order to do this with public methods created during construction, you'd have to assign the new method to each instance that has been created, which is an awkward task. 为了使用在构造过程中创建的公共方法来执行此操作,您必须将新方法分配给已创建的每个实例,这是一项艰巨的任务。 This is because ins1 and ins2 would have their own, individually created calc() functions. 这是因为ins1ins2将拥有自己的,单独创建的calc()函数。

Another side effect of creating methods inside the constructor is poorer performance. 在构造函数内部创建方法的另一个副作用是性能较差。 Each method has to be created every time the constructor function runs. 每次构造函数运行时,都必须创建每个方法。 Methods on the prototype chain are created once and then "inherited" by each instance. 原型链上的方法创建一次,然后由每个实例“继承”。 On the flip side of the coin, public methods have access to "private" variables, which isn't possible with inherited methods. 另一方面,公共方法可以访问“私有”变量,而继承方法则不可能。

As for your function Class() {} vs var Class = function () {} question, the former is "hoisted" to the top of the current scope before execution. 至于您的function Class() {}var Class = function () {}问题,在执行之前,将前者“提升”到当前作用域的顶部。 For the latter, the variable declaration is hoisted, but not the assignment. 对于后者,将悬挂变量声明,而不是赋值。 For example: 例如:

// Error, fn is called before the function is assigned!fn();var fn = function () { alert("test!"); } // Works as expected: the fn2 declaration is hoisted above the callfn2();function fn2() { alert("test!"); }

#4楼

The advantage of the prototype approach is efficiency. 原型方法的优点是效率。 There is one calc() function object shared between all Class objects (by which I mean objects created by calling the Class constructor). 所有Class对象之间共享一个calc()函数对象(我的意思是通过调用Class构造函数创建的对象)。 The other way (assigning methods within the constructor) creates a new function object for every Class object, using more memory and taking more processing time when calling the Class constructor. 另一种方法(在构造函数中分配方法)为每个Class对象创建一个新的函数对象,在调用Class构造函数时使用更多的内存并占用更多的处理时间。 However, this approach does have an advantage: the calc() method has access to local variables within the constructor, which you can use to your advantage: 但是,这种方法确实有一个优势: calc()方法可以访问构造函数中的局部变量,您可以利用它来发挥自己的优势:

function Class() {    var calcCallCount = 0;    this.calc = function (a, b) {        ++calcCallCount;        alert("Calc called " + calcCallCount + " times");        return a + b;    };};

Regarding var Class = function() {...} versus function Class() {...} , I generally prefer the latter is because it means the function has a name, which can be useful when debugging. 关于var Class = function() {...}function Class() {...} ,我通常更喜欢后者,因为它意味着函数具有名称,这在调试时很有用。 The other difference is that the latter version (a function declaration ) is hoisted, meaning that it is available everywhere within the scope in which it is defined, not just after the definition. 另一个不同之处是,悬挂了后一个版本( 函数声明 ),这意味着它在定义它的范围内的任何地方都可用,而不仅仅是在定义之后。 However, prefer to use the former (a function expression ) everywhere. 但是, 喜欢在各处使用前者(一个函数表达式 )。


#5楼

var YourClass = function(){  var privateField = "somevalue";  this.publicField = "somevalue";  this.instanceMethod1 = function(){     //you may access both private and public field from here:     //in order to access public field, you must use "this":     alert(privateField + "; " + this.publicField);  };}YourClass.prototype.instanceMethod2 = function(){  //you may access only public field 2 from this method, but not private fields:  alert(this.publicField);  //error: drawaback of prototype methods:  alert(privateField);  };

Advantages of prototype methods: 原型方法的优点:

  1. When you define methods via prototype, they are shared among all YourClass instances. 当您通过原型定义方法时,它们将在所有YourClass实例之间共享。 As a result the total size of such instances is < than if you define methods in constructor; 因此,与在构造函数中定义方法相比,此类实例的总大小为<; There are tests that show how method definition via prototype decrease the total size of html page and as a result a speed of its loading. 有测试显示了通过原型进行方法定义如何减少html页面的总大小,以及如何降低html页面的加载速度。

  2. another advantage of methods, defined via prototype - is when you use inherited classes, you may override such methods and in the overriden method of the derived class you may invoke the method of base class with the same name, but with methods defined in constructor, you cannot do this. 通过原型定义的方法的另一个优势-当您使用继承的类时,您可以覆盖此类方法,并且在派生类的重写方法中,可以使用具有相同名称但在构造函数中定义的方法来调用基类的方法,你不可以做这个。

转载地址:http://uzjnb.baihongyu.com/

你可能感兴趣的文章
RandomAccessFile可实现数据的分段写入也就是多线程下载
查看>>
DataInputStream与DataOutputStream用于操作基本数据类型的数据的流对象
查看>>
ByteArrayStream用于操作字节数组的流对象
查看>>
IO流-字符编码表转换示例
查看>>
IO流-转换流的字符编码转换-ISO-8859-1和utf-8和GBK互转
查看>>
网络游戏线上活动的类型及特点(二)
查看>>
sleeping-to-save-cpu
查看>>
键盘符号英语读法
查看>>
[转]char_traits
查看>>
[转载] 人生三重境界
查看>>
[转载]学习时注意思考方法
查看>>
C10K问题
查看>>
STL 线程安全性
查看>>
Writing Reentrant and Thread-Safe Code(编写可重入和线程安全的代码)
查看>>
可重入性
查看>>
无闪烁刷屏技术的实现
查看>>
Crazybit开发手记(一):设计之数据结构和算法的分离
查看>>
Windows消息
查看>>
Windows线程及同步机制
查看>>
CImage类
查看>>