在JavaScript中创建构造函数时,最佳做法是什么? [重复]

时间:2023-02-06 21:15:33

This question already has an answer here:

这个问题在这里已有答案:

So I've been trying to figure out prototypal inheritance in Javascript and I'm still confused on one point. Let's say I want to make a constructor function for a person with a few functions of it's own.

所以我一直试图在Javascript中找出原型继承,我仍然对一点感到困惑。假设我想为一个拥有它自己的一些函数的人创建一个构造函数。

function Person(name) {
  this.name = name;
  this.sayName = function() {
    console.log("My name is " + name);
  }
}

var john = new Person("John");

john.sayName();

So in this case I've created an object and called a function, however this doesn't seem to be the efficient way to do it. Another example I've seen this is this:

所以在这种情况下我创建了一个对象并调用了一个函数,但这似乎并不是一种有效的方法。我见过的另一个例子是:

function Person(name) {
  this.name = name;
}
Person.prototype.sayName = function() {
  console.log("My name is " + name);
}

var john = new Person("John");

john.sayName();

Now I've read that the second object is more efficient because it's not storing the sayName function within itself, instead it's going up the prototype chain until it finds it within Persons prototype object.

现在我已经读到第二个对象更有效率,因为它没有将sayName函数存储在其自身内,而是在原型链上升,直到它在Persons原型对象中找到它。

What I'm unsure about is which I should use for complicated constructor functions. The first snippet, in my opinion, is much much easier to read than the second because there is a clear hierarchical structure to it, but the second snippet is supposedly more efficient.

我不确定的是我应该用于复杂的构造函数。在我看来,第一个片段比第二个片段更容易阅读,因为它有一个清晰的层次结构,但第二个片段据说效率更高。

In a real world scenario, which style of constructor function would I be more likely to use?

在现实世界的场景中,我更有可能使用哪种构造函数?

Edit: I have a follow up question. Is there any way to make the second snippet more readable?

编辑:我有一个跟进问题。有没有办法让第二个片段更具可读性?

4 个解决方案

#1


0  

Generally if you are going to have a class from which several instances will be created, you should add the methods to the prototype object. The main reason I believe is that all the instances of a class would reference the prototype object, and won't copy it. So if the prototype object changes, it would be reflected in the prototype object referenced by all the instances.

通常,如果要创建一个将从中创建多个实例的类,则应将方法添加到原型对象中。我相信的主要原因是类的所有实例都会引用原型对象,而不会复制它。因此,如果原型对象发生更改,它将反映在所有实例引用的原型对象中。

This is better than the first option where each method is created (copied) on each instance. And so a lot of instances would also mean a lot of those methods will be created, occupying memory. But in the second option, they all use the single method created on the prototype object.

这比在每个实例上创建(复制)每个方法的第一个选项更好。所以很多实例也意味着会创建很多这些方法,占用内存。但在第二个选项中,它们都使用在原型对象上创建的单个方法。

#2


0  

if you use the first one , you'll be creating a new function object for sayName each time the constructor is called, while in the second way you avoid that overhead.

如果你使用第一个,你将在每次调用构造函数时为sayName创建一个新的函数对象,而在第二种方法中你可以避免这种开销。

if you use a reference type in your constructor it will be shared, for ex :

如果你在构造函数中使用引用类型,它将被共享,例如:

    function Person(name){
    this.name = name;
    this.hobbies = [..some hobbies];
}

now hobbies will be shared by every object you create with this constructor , so it's best to put shared properties on prototype and only use unique one's in the constructor

现在爱好将由您使用此构造函数创建的每个对象共享,因此最好将共享属性放在原型上,并且只在构造函数中使用唯一的属性

#3


0  

In the first approach will create method function for every single instance. In the second one, all instances share the method defined in the prototype. So the second approach is better because of saving memory.

在第一种方法中,将为每个实例创建方法函数。在第二个实例中,所有实例共享原型中定义的方法。所以第二种方法更好,因为节省了内存。

However, ECMAScript 6 is officially released several months ago, so why not try class:

但是,ECMAScript 6几个月前正式发布,所以为什么不尝试上课:

class Person {
  constructor(name) {
    this.name = name;
  }

  sayName() {
    console.log("My name is " + this.name);
  }
}

var john = new Person("John");
john.sayName(); // "My name is John"

The feature is not well supported yet, if you want backward compatibility in browsers, use Babel.

该功能尚未得到很好的支持,如果您想要在浏览器中向后兼容,请使用Babel。

#4


0  

Another syntax introduced in ECMAScript 5 for create instances of Classes is:

ECMAScript 5中为类的创建实例引入的另一种语法是:

Object.create(prototype [, propertiesObject ] )

Example:

var MyClass = function (param) {
    this.field1 = param;
}
MyClass.prototype.changeField = function(param){
    this.field1 = param;
}
var instance = Object.create(MyClass.prototype);

If you are interested in learn advanced things about javascript I suggest a book called "Mastering Javascript design patterns".

如果您有兴趣学习关于javascript的高级内容,我建议使用一本名为“掌握Javascript设计模式”的书。

#1


0  

Generally if you are going to have a class from which several instances will be created, you should add the methods to the prototype object. The main reason I believe is that all the instances of a class would reference the prototype object, and won't copy it. So if the prototype object changes, it would be reflected in the prototype object referenced by all the instances.

通常,如果要创建一个将从中创建多个实例的类,则应将方法添加到原型对象中。我相信的主要原因是类的所有实例都会引用原型对象,而不会复制它。因此,如果原型对象发生更改,它将反映在所有实例引用的原型对象中。

This is better than the first option where each method is created (copied) on each instance. And so a lot of instances would also mean a lot of those methods will be created, occupying memory. But in the second option, they all use the single method created on the prototype object.

这比在每个实例上创建(复制)每个方法的第一个选项更好。所以很多实例也意味着会创建很多这些方法,占用内存。但在第二个选项中,它们都使用在原型对象上创建的单个方法。

#2


0  

if you use the first one , you'll be creating a new function object for sayName each time the constructor is called, while in the second way you avoid that overhead.

如果你使用第一个,你将在每次调用构造函数时为sayName创建一个新的函数对象,而在第二种方法中你可以避免这种开销。

if you use a reference type in your constructor it will be shared, for ex :

如果你在构造函数中使用引用类型,它将被共享,例如:

    function Person(name){
    this.name = name;
    this.hobbies = [..some hobbies];
}

now hobbies will be shared by every object you create with this constructor , so it's best to put shared properties on prototype and only use unique one's in the constructor

现在爱好将由您使用此构造函数创建的每个对象共享,因此最好将共享属性放在原型上,并且只在构造函数中使用唯一的属性

#3


0  

In the first approach will create method function for every single instance. In the second one, all instances share the method defined in the prototype. So the second approach is better because of saving memory.

在第一种方法中,将为每个实例创建方法函数。在第二个实例中,所有实例共享原型中定义的方法。所以第二种方法更好,因为节省了内存。

However, ECMAScript 6 is officially released several months ago, so why not try class:

但是,ECMAScript 6几个月前正式发布,所以为什么不尝试上课:

class Person {
  constructor(name) {
    this.name = name;
  }

  sayName() {
    console.log("My name is " + this.name);
  }
}

var john = new Person("John");
john.sayName(); // "My name is John"

The feature is not well supported yet, if you want backward compatibility in browsers, use Babel.

该功能尚未得到很好的支持,如果您想要在浏览器中向后兼容,请使用Babel。

#4


0  

Another syntax introduced in ECMAScript 5 for create instances of Classes is:

ECMAScript 5中为类的创建实例引入的另一种语法是:

Object.create(prototype [, propertiesObject ] )

Example:

var MyClass = function (param) {
    this.field1 = param;
}
MyClass.prototype.changeField = function(param){
    this.field1 = param;
}
var instance = Object.create(MyClass.prototype);

If you are interested in learn advanced things about javascript I suggest a book called "Mastering Javascript design patterns".

如果您有兴趣学习关于javascript的高级内容,我建议使用一本名为“掌握Javascript设计模式”的书。