Los métodos son una de las partes más importantes de las clases, ya que en ellos incluimos las funciones que queremos que trabajen sobre nuestro objeto. Los métodos tienen un modelo específico de definición y funcionamiento.
métodos en el prototipo
class | function |
class C { method () { return 2; } } const c = new C(); console.assert( c.method() === 2 ); | function C () { } C.prototype.method = function () { return 2; }; const c = new C(); console.assert( c.method() === 2 ); |
En class
los métodos se escriben dentro del cuerpo de la clase, de forma similar a como hacemos con el constructor. Estas funciones se se incorporan automáticamente como miembros del prototipo de la clase.
Con function
debemos añadir directamente los métodos como miembro del objeto prototype
para que se comporten de igual forma que con class
.
métodos en el objeto
class | function |
class C { constructor () { this.method1 = function () { return 1; } } method2 () { return 2; } } const c = new C(); console.assert( c.method1() === 1 ); console.assert( !('method1' in C.prototype) ); console.assert( c.method2() === 2 ); console.assert( 'method2' in C.prototype ); | function C () { this.method1 = function () { return 1; } } C.prototype.method2 = function () { return 2; }; const c = new C(); console.assert( c.method1() === 1 ); console.assert( !('method1' in C.prototype) ); console.assert( c.method2() === 2 ); console.assert( 'method2' in C.prototype ); |
En general los métodos se definen a nivel de prototipo, ya que compartir las funciones entre todos los objetos de la misma clase no causa ningún conflicto. No obstante, nada nos impide crear métodos directamente sobre el objeto, por ejemplo, en el constructor. A partir de ese momento estos métodos son parte del objeto y no de su prototipo.
métodos no enumerables
class | function |
class C { method () { } } console.assert( ! C.prototype.propertyIsEnumerable( 'method' ) ); const c = new C(); console.assert( ! c.propertyIsEnumerable( 'method' ) ); | function C () { } C.prototype.method = function () { return 1; }; console.assert( C.prototype.propertyIsEnumerable( 'method' ) ); const c = new C(); console.assert( ! c.propertyIsEnumerable( 'method' ) ); |
Los miembros creados sobre el prototipo no son enumerables en el objeto, es decir, no son significativos a la hora de recorrer las propiedades del objeto en un bucle for...in
. En el caso de utilizar function
, normalmente el método es enumerable en el prototipo, pero deja de ser enumerable en el objeto. Cualquier configuración que hagamos sobre enumeración en los miembros del prototipo no tendrá efecto sobre el objeto.
Los métodos creados directamente sobre el objeto son enumerables, y eso no suele ser el comportamiento que deseamos, por lo que suele ser conveniente utilizar Object.defineProperty()
o Object.defineProperties()
para cambiar su condición a no enumerables.
class | function |
class C { constructor () { Object.defineProperty( this, 'method', { value : function () { return 1; }, enumerable : false } ); } } const c = new C(); console.assert( ! c.propertyIsEnumerable( 'method' ) ); | function C () { Object.defineProperty( this, 'method', { value : function () { return 1; }, enumerable : false } ); } const c = new C(); console.assert( ! c.propertyIsEnumerable( 'method' ) ); |
Aunque lo habitual es dejar los métodos como no enumerables, en nuestra mano decidir como queremos que se comporten los métodos a este respecto.
this
Cuando se ejecutan los métodos tendrán this
dirigido al objeto concreto en el que se está invocando el método y no a la función.
class | function |
class C { method () { console.assert( this instanceof C ); } } const c = new C(); c.method(); | function C () { } C.prototype.method = function () { console.assert( this instanceof C ); }; const c = new C(); c.method(); |
Tenemos que saber que cuando se invoca a un método es posible modificar su this
por medio de los parámetros de los métodos .call()
y .apply()
que tiene todas las funciones.
strict mode
class | function |
class C { constructor () { a = 10; /* throw an error in strict mode */ } } try { const c = new C(); console.assert( false ); } catch (err) { console.assert( err.message === 'a is not defined' ); } | function C () { 'use strict'; a = 10; /* throw an error in strict mode */ } try { const c = new C(); console.assert( false ); } catch (err) { console.assert( err.message === 'a is not defined' ); } |
Los constructores y métodos definidos en una instrucción class
son ejecutados implicitamente bajo la cláusula script mode
. Esto suele ser bastante útil para asegurarnos que utilizamos un Javascript bien construido.
Por el contrario, en el caso de function
la cláusula script mode
debe ser incluida de forma explícita para evitar los problemas de funcionamiento en sloppy mode o modo poco riguroso.
propiedades | Índice | métodos de acceso y datos privados |