2011-01-14 20 views
46

Estoy creando una clase Vector, que básicamente puede contener tres valores numéricos. Sin embargo, se pueden realizar muchas operaciones con dicho vector, p. obtener la magnitud, sumar o restar otro vector, etc.¿Debo usar un prototipo o no?

Me preguntaba si estas funciones deberían codificarse como una función prototipo de la clase Vector, o si debería definirlas en el constructor.

Entonces, ¿cuál de estos dos métodos es preferible?

function Vector3D(x, y, z) { 
    this.x = x; 
    this.y = y 
    this.z = z; 
} 

Vector3D.prototype.magnitude = function() { 
    return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); 
}; 

o

function Vector3D(x, y, z) { 
    this.x = x; 
    this.y = y; 
    this.z = z; 

    this.magnitude = function() { 
     return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); 
    }; 
} 

Respuesta

49

Esta es exactamente la situación para usar el prototipo. Veo dos beneficios principales para hacerlo:

  1. Las funciones no se crean varias veces. Si define las funciones dentro del constructor, se crea una nueva función anónima para cada función que defina, cada vez que se llame al constructor. Los prototipos son objetos estáticos, y cada instancia de Vector3D simplemente referencia las funciones del prototipo.
  2. El prototipo es un solo objeto que se puede manipular fácilmente. Esto ofrece una gran flexibilidad; Lamentablemente, solo puedo ofrecer algunos ejemplos de lo que esto puede ofrecer:
    1. Si desea crear una clase secundaria, por ejemplo Vector3DSpecial, puede simplemente clonar Vector3D.prototype y asignarla al Vector3DSpecial.prototype. Si bien también puede hacer esto usando constructores por Vector3DSpecial.prototype = new Vector3D();, los constructores pueden contener efectos secundarios que se ejecutarán en esa simple asignación de prototipo, y por lo tanto deben evitarse. Con los prototipos, incluso puede elegir solo funciones particulares en el prototipo que se copiarán en la nueva clase.
    2. La adición de métodos al Vector3D es simplemente una cuestión de agregar propiedades al prototipo, y permite que su código se divida más fácilmente/organice en varios archivos, o permita agregar métodos en otras partes del código dinámicamente. Claro, puedes hacer una combinación de métodos de adición en el constructor y en el prototipo, pero eso es inconsistente y es probable que conduzca a una mayor complejidad más adelante en la pista.

Cuándo me no uso prototipo? Para objetos únicos, por ejemplo, un controlador que interactúa con una página y puede delegar el trabajo en otros objetos. Un objeto global de "notificación" es uno de esos ejemplos. En este caso, la extensión es poco probable, y el objeto solo se crea una vez, lo que hace que el prototipo sea una complejidad adicional (conceptual).

8

métodos prototipo sólo funcionaría para los bienes de dominio público, si desea realizar un seguimiento de x, y, z como variables "privado" el prototipo no funcionaría.

Usaría este último, porque es posible que desee métodos que solo funcionan con variables privadas/internas, pero todo depende del contexto.

function Vector3D(x, y, z) { 
    // x, y, z is automatically in this scope now, but as private members. 
    this.magnitude = function() { 
     return Math.sqrt(x * x + y * y + z *z); 
    } 
} 
+1

Gracias por su reacción. x, y y z también deberían poder extraerse de una instancia de Vector3D, por lo que deberían ser públicos. En este caso, ¿el prototipo sería la mejor opción? – pimvdb

+3

+1 para la respuesta correcta, pero prefiero los prototipos, ya que cualquier cosa privada en js es una generación de energía, y por lo general solo hará que sea más difícil para usted probar su código. ¿De quién está ocultando las cosas excepto usted mismo? –

+0

Acepto Contigo, por lo tanto, solo tengo variables públicas. En las herramientas de desarrollo de Google Chrome, las funciones también se muestran como miembros si pasaron por el constructor, mientras que sería más práctico si estuvieran 'ocultos' en el prototipo y solo se mostrarán x, yyz allí. – pimvdb

0

ECMA 6 http://es6-features.org/#BaseClassAccess

class Shape { 
    … 
    toString() { 
     return `Shape(${this.id})` 
    } 
} 
class Rectangle extends Shape { 
    constructor (id, x, y, width, height) { 
     super(id, x, y) 
     … 
    } 
    toString() { 
     return "Rectangle > " + super.toString() 
    } 
} 
class Circle extends Shape { 
    constructor (id, x, y, radius) { 
     super(id, x, y) 
     … 
    } 
    toString() { 
     return "Circle > " + super.toString() 
    } 
} 

ECMA 5

var Shape = function (id, x, y) { 
    … 
}; 
Shape.prototype.toString = function (x, y) { 
    return "Shape(" + this.id + ")" 
}; 
var Rectangle = function (id, x, y, width, height) { 
    Shape.call(this, id, x, y); 
    … 
}; 
Rectangle.prototype.toString = function() { 
    return "Rectangle > " + Shape.prototype.toString.call(this); 
}; 
var Circle = function (id, x, y, radius) { 
    Shape.call(this, id, x, y); 
    … 
}; 
Circle.prototype.toString = function() { 
    return "Circle > " + Shape.prototype.toString.call(this); 
};