variable nodejs es6 clases attribute javascript oop

nodejs - Clase contra método estático en JavaScript



nodejs class (13)

Además, ahora es posible hacerlo con class y static

''use strict'' class Foo { static talk() { console.log(''talk'') }; speak() { console.log(''speak'') }; };

daré

var a = new Foo(); Foo.talk(); // ''talk'' a.talk(); // err ''is not a function'' a.speak(); // ''speak'' Foo.speak(); // err ''is not a function''

Sé que esto funcionará:

function Foo() {}; Foo.prototype.talk = function () { alert(''hello~/n''); }; var a = new Foo; a.talk(); // ''hello~/n''

Pero si quiero llamar

Foo.talk() // this will not work Foo.prototype.talk() // this works correctly

Encuentro algunos métodos para hacer que Foo.talk funcione,

  1. Foo.__proto__ = Foo.prototype
  2. Foo.talk = Foo.prototype.talk

¿Hay alguna otra manera de hacer esto? No sé si es correcto hacerlo. ¿Utiliza métodos de clase o métodos estáticos en su código JavaScript?


Cuando intentas llamar a Foo.talk , el JS intenta buscar una función a través de __proto__ y, por supuesto, no se puede encontrar.

Foo.__proto__ es Function.prototype .


Cuando me enfrenté a una situación así, he hecho algo como esto:

Logger = { info: function (message, tag) { var fullMessage = ''''; fullMessage = this._getFormatedMessage(message, tag); if (loggerEnabled) { console.log(fullMessage); } }, warning: function (message, tag) { var fullMessage = ''''; fullMessage = this._getFormatedMessage(message, tag); if (loggerEnabled) { console.warn(fullMessage);`enter code here` } }, _getFormatedMessage: function () {} };

así que ahora puedo llamar al método de información como Logger.info("my Msg", "Tag");


ES6 admite ahora palabras clave de class y static como un encanto:

class Foo { constructor() {} talk() { console.log("i am not static"); } static saying() { console.log(this.speech); } static get speech() { return "i am static method"; } }


En primer lugar, recuerde que JavaScript es principalmente un lenguaje prototípico , en lugar de un lenguaje basado en clases 1 . Foo no es una clase, es una función, que es un objeto. Puede crear una instancia de un objeto desde esa función usando la new palabra clave que le permitirá crear algo similar a una clase en un lenguaje estándar de POO.

Yo sugeriría ignorar __proto__ mayor parte del tiempo porque no es compatible con el navegador cruzado, y en su lugar se enfoca en aprender cómo funciona el prototype .

Si tiene una instancia de un objeto creado a partir de una función 2 y accede a uno de sus miembros (métodos, atributos, propiedades, constantes, etc.) de cualquier manera, el acceso fluirá hacia la jerarquía del prototipo hasta que (a) encuentre el miembro, o (b) no encuentra otro prototipo.

La jerarquía comienza en el objeto al que se llamó, y luego busca su objeto prototipo. Si el objeto prototipo tiene un prototipo, se repite, si no existe un prototipo, se devuelve undefined .

Por ejemplo:

foo = {bar: ''baz''}; alert(foo.bar); //alerts "baz" foo = {}; alert(foo.bar); //alerts undefined function Foo(){} Foo.prototype = {bar: ''baz''}; f = new Foo(); alert(f.bar); //alerts "baz" because the object f doesn''t have an attribute "bar" //so it checks the prototype f.bar = ''buzz''; alert( f.bar ); //alerts "buzz" because f has an attribute "bar" set

Me parece que al menos ya has comprendido estas partes "básicas", pero necesito hacerlas explícitas solo para estar seguro.

En JavaScript, todo es un objeto 3 .

Todo es un objeto.

function Foo(){} no solo define una nueva función, sino que define un nuevo objeto de función al que se puede acceder utilizando Foo .

Esta es la razón por la que puede acceder al prototipo de Foo con Foo.prototype .

Lo que también puedes hacer es configurar más funciones en Foo :

Foo.talk = function () { alert(''hello world!''); };

Se puede acceder a esta nueva función usando:

Foo.talk();

Espero que ya esté notando una similitud entre las funciones de un objeto de función y un método estático.

Piensa en f = new Foo(); como creando una instancia de clase, Foo.prototype.bar = function(){...} como definiendo un método compartido para la clase, y Foo.baz = function(){...} como definiendo un método estático público para clase.

ECMAScript 2015 introdujo una variedad de azúcar sintáctica para este tipo de declaraciones para hacerlas más fáciles de implementar y también para que sean más fáciles de leer. El ejemplo anterior se puede escribir como:

class Foo { bar() {...} static baz() {...} }

lo que permite llamar a bar como:

const f = new Foo() f.bar()

y baz ser llamado como:

Foo.baz()

1: la class era una "Palabra reservada para el futuro" en la especificación ECMAScript 5 , pero ES6 introduce la capacidad de definir clases usando la palabra clave de class .

2: esencialmente una instancia de clase creada por un constructor, pero hay muchas diferencias matizadas que no quiero engañarles

3: los valores primitivos —que incluyen valores undefined , null , booleanos, números y cadenas— no son objetos técnicamente porque son implementaciones de lenguaje de bajo nivel. Los booleanos, los números y las cadenas aún interactúan con la cadena del prototipo como si fueran objetos, por lo que, a los efectos de esta respuesta, es más fácil considerarlos "objetos" aunque no lo sean tanto.


En tu caso, si quieres Foo.talk() :

function Foo() {}; // But use Foo.talk would be inefficient Foo.talk = function () { alert(''hello~/n''); }; Foo.talk(); // ''hello~/n''

Pero es una forma ineficiente de implementar, usar prototype es mejor.

Otra forma, Mi camino se define como clase estática:

var Foo = new function() { this.talk = function () { alert(''hello~/n''); }; }; Foo.talk(); // ''hello~/n''

La clase estática no necesita usar prototype porque solo se construirá una vez como uso estático.

https://github.com/yidas/js-design-patterns/tree/master/class


Este es un buen ejemplo para demostrar cómo funciona Javascript con variables y métodos estáticos / de instancia.

function Animal(name) { Animal.count = Animal.count+1||1;// static variables, use function name "Animal" this.name = name; //instance variable, using "this" } Animal.showCount = function () {//static method alert(Animal.count) } Animal.prototype.showName=function(){//instance method alert(this.name); } var mouse = new Animal("Mickey"); var elephant = new Animal("Haddoop"); Animal.showCount(); // static method, count=2 mouse.showName();//instance method, alert "Mickey" mouse.showCount();//Error!! mouse.showCount is not a function, which is different from Java


Las llamadas a métodos estáticos se realizan directamente en la clase y no se pueden llamar en instancias de la clase. Los métodos estáticos se utilizan a menudo para crear la función de utilidad

Descripción bastante clara

Tomado directamente de mozilla.org

Foo debe estar vinculado a su clase. Luego, cuando cree una nueva instancia, puede llamar a myNewInstance.foo () Si importa su clase, puede llamar a un método estático.


Llama a un método estático desde una instancia:

function Clazz() {}; Clazz.staticMethod = function() { alert(''STATIC!!!''); }; Clazz.prototype.func = function() { this.constructor.staticMethod(); } var obj = new Clazz(); obj.func(); // <- Alert''s "STATIC!!!"

Proyecto de clase de Javascript simple: https://github.com/reduardo7/sjsClass


Lo puedes lograr de la siguiente manera:

function Foo() {}; Foo.talk = function() { alert(''I am talking.''); };

Ahora puedes invocar la función "hablar" como se muestra a continuación:

Foo.talk();

Puedes hacer esto porque en JavaScript, las funciones también son objetos. "zzzzBov" también lo ha respondido pero es una lectura larga.


Si tienes que escribir métodos estáticos en ES5, encontré un excelente tutorial para eso:

//Constructor var Person = function (name, age){ //private properties var priv = {}; //Public properties this.name = name; this.age = age; //Public methods this.sayHi = function(){ alert(''hello''); } } // A static method; this method only // exists on the class and doesn''t exist // on child objects Person.sayName = function() { alert("I am a Person object ;)"); };

vea @ https://abdulapopoola.com/2013/03/30/static-and-instance-methods-in-javascript/


Solo notas adicionales. Usando la clase ES6, cuando creamos métodos estáticos ... el motor Javacsript configuró el atributo descriptor en un poco diferente del método "estático" de la vieja escuela

function Car() { } Car.brand = function() { console.log(''Honda''); } console.log( Object.getOwnPropertyDescriptors(Car) );

establece el atributo interno (propiedad del descriptor) para la marca () en

.. brand: [object Object] { configurable: true, enumerable: true, value: .. writable: true } ..

comparado con

class Car2 { static brand() { console.log(''Honda''); } } console.log( Object.getOwnPropertyDescriptors(Car2) );

que establece el atributo interno para la marca () a

.. brand: [object Object] { configurable: true, enumerable: false, value:.. writable: true } ..

ver que enumerable se establece en falso para el método estático en ES6.

significa que no puede usar el bucle for-in para verificar el objeto

for (let prop in Car) { console.log(prop); // brand } for (let prop in Car2) { console.log(prop); // nothing here }

El método estático en ES6 se trata como la propiedad privada de otra clase (nombre, longitud, constructor), excepto que el método estático aún se puede escribir, por lo que el descriptor se puede establecer en true { writable: true } . también significa que podemos anularlo

Car2.brand = function() { console.log(''Toyota''); }; console.log( Car2.brand() // is now changed to toyota );


Yo uso espacios de nombres:

var Foo = { element: document.getElementById("id-here"), Talk: function(message) { alert("talking..." + message); }, ChangeElement: function() { this.element.style.color = "red"; } };

Y para usarlo:

Foo.Talk("Testing");

O

Foo.ChangeElement();