tablas - obtener datos de una tabla html javascript
Cómo implementar un método privado en la clase ES6 con Traceur (9)
¿Has considerado usar las funciones de fábrica? Por lo general, son una alternativa mucho mejor a las clases o funciones de constructor en Javascript. Aquí hay un ejemplo de cómo funciona:
function car () {
var privateVariable = 4
function privateFunction () {}
return {
color: ''red'',
drive: function (miles) {},
stop: function() {}
....
}
}
Gracias a los cierres, tiene acceso a todas las funciones privadas y variables dentro del objeto devuelto, pero no puede acceder a ellas desde el exterior.
Esta pregunta ya tiene una respuesta aquí:
- Propiedades privadas en JavaScript ES6 clases 35 respuestas
Utilizo el compilador Traceur para tener ventaja con las funciones de ES6 ahora.
Quiero implementar esto desde ES5:
function Animal() {
var self = this,
sayHi;
sayHi = function() {
self.hi();
};
this.hi = function() {/* ... */}
}
Actualmente, traceur no admite palabras clave
private
y
public
(
de la armonía
).
Y la sintaxis de clase ES6 no permite usar declaraciones
var
(o
let
) simples en el cuerpo de la clase.
La única forma que encuentro es simular privates antes de la declaración de clase. Algo como:
var sayHi = function() {
// ... do stuff
};
class Animal {
...
Es mejor que nada, pero como se esperaba, no puede pasar
this
correctamente al método privado sin
apply
o
bind
cada vez.
Entonces, ¿hay alguna posibilidad de usar datos privados en la clase ES6 compatible con el compilador traceur?
Aunque actualmente no hay forma de declarar un método o propiedad como privado, los módulos ES6 no están en el espacio de nombres global . Por lo tanto, todo lo que declare en su módulo y no exporte no estará disponible para ninguna otra parte de su programa , pero seguirá estando disponible para su módulo durante el tiempo de ejecución. Por lo tanto, tiene propiedades y métodos privados :)
Aquí hay un ejemplo (en el archivo
test.js
)
function tryMe1(a) {
console.log(a + 2);
}
var tryMe2 = 1234;
class myModule {
tryMe3(a) {
console.log(a + 100);
}
getTryMe1(a) {
tryMe1(a);
}
getTryMe2() {
return tryMe2;
}
}
// Exports just myModule class. Not anything outside of it.
export default myModule;
En otro archivo
import MyModule from ''./test'';
let bar = new MyModule();
tryMe1(1); // ReferenceError: tryMe1 is not defined
tryMe2; // ReferenceError: tryMe2 is not defined
bar.tryMe1(1); // TypeError: bar.tryMe1 is not a function
bar.tryMe2; // undefined
bar.tryMe3(1); // 101
bar.getTryMe1(1); // 3
bar.getTryMe2(); // 1234
Como dice alexpods, no hay una forma dedicada de hacer esto en ES6. Sin embargo, para los interesados, también hay una propuesta para el operador de enlace que permite este tipo de sintaxis:
function privateMethod() {
return `Hello ${this.name}`;
}
export class Animal {
constructor(name) {
this.name = name;
}
publicMethod() {
this::privateMethod();
}
}
Una vez más, esto es solo una propuesta. Su experiencia puede ser diferente.
Como ya dijo :
Aunque actualmente no hay forma de declarar un método o propiedad como privado, los módulos ES6 no están en el espacio de nombres global. Por lo tanto, todo lo que declare en su módulo y no exporte no estará disponible para ninguna otra parte de su programa, pero seguirá estando disponible para su módulo durante el tiempo de ejecución.
Pero su ejemplo no mostró cómo el método privado podría acceder a los miembros de la instancia de la clase. nos muestra algunos buenos ejemplos de cómo acceder a los miembros de la instancia a través del enlace o la alternativa de usar un método lambda en el constructor, pero me gustaría agregar una forma más simple de hacerlo: pasar la instancia como un parámetro al método privado. Hacerlo de esta manera llevaría a Max''s MyClass a verse así:
function myPrivateFunction(myClass) {
console.log("My property: " + myClass.prop);
}
class MyClass() {
constructor() {
this.prop = "myProp";
}
testMethod() {
myPrivateFunction(this);
}
}
module.exports = MyClass;
De qué manera lo haces realmente se reduce a la preferencia personal.
Espero que esto pueda ser útil. :)
I. Declarando vars, funciones dentro de IIFE (expresión de función invocada inmediatamente) , estas solo pueden usarse en la función anónima. (Puede ser bueno usar palabras clave "let, const" sin usar ''var'' cuando necesite cambiar el código para ES6).
let Name = (function() {
const _privateHello = function() {
}
class Name {
constructor() {
}
publicMethod() {
_privateHello()
}
}
return Name;
})();
II El objeto WeakMap puede ser bueno para problemas de pérdida de memoria.
Las variables almacenadas en WeakMap se eliminarán cuando se elimine la instancia. Mira este artículo. ( Gestión de datos privados de clases ES6 )
let Name = (function() {
const _privateName = new WeakMap();
})();
III. Pongamos todo junto.
let Name = (function() {
const _privateName = new WeakMap();
const _privateHello = function(fullName) {
console.log("Hello, " + fullName);
}
class Name {
constructor(firstName, lastName) {
_privateName.set(this, {firstName: firstName, lastName: lastName});
}
static printName(name) {
let privateName = _privateName.get(name);
let _fullname = privateName.firstName + " " + privateName.lastName;
_privateHello(_fullname);
}
printName() {
let privateName = _privateName.get(this);
let _fullname = privateName.firstName + " " + privateName.lastName;
_privateHello(_fullname);
}
}
return Name;
})();
var aMan = new Name("JH", "Son");
aMan.printName(); // "Hello, JH Son"
Name.printName(aMan); // "Hello, JH Son"
No hay palabras clave
private
,
public
o
protected
en la
especificación
actual de
ECMAScript 6
.
Entonces Traceur no es compatible con lo
private
y lo
public
.
6to5 (actualmente se llama "Babel") realiza
esta propuesta
con fines experimentales (ver también
esta discusión
).
Pero es solo una propuesta, después de todo.
Entonces, por ahora, puede simular propiedades privadas a través de
WeakMap
(ver
here
).
Otra alternativa es
Symbol
, pero no proporciona privacidad real ya que se puede acceder fácilmente a la propiedad a través de
Object.getOwnPropertySymbols
.
En mi humilde opinión, la mejor solución en este momento, simplemente use pseudo privacidad.
Si usa con frecuencia
apply
o
call
con su método, entonces este método es muy específico de un objeto.
Por lo tanto, vale la pena declararlo en su clase solo con el prefijo de subrayado:
class Animal {
_sayHi() {
// do stuff
}
}
Puedes usar Symbol
var say = Symbol()
function Cat(){
this[say]() // call private methos
}
Cat.prototype[say] = function(){ alert(''im a private'') }
PS alexpods no es correcto. obtiene protección en lugar de privacidad, ya que la herencia es un conflicto de nombres
En realidad, puede usar
var say = String(Math.random())
lugar de Symbol
EN ES6:
var say = Symbol()
class Cat {
constructor(){
this[say]() // call private
}
[say](){
alert(''im private'')
}
}
Se me ocurrió lo que creo que es una solución mucho mejor que permite:
-
no es necesario ''this._'', that / self, mapas débiles, símbolos, etc. Código de ''clase'' claro y directo
-
Las variables y métodos privados son realmente privados y tienen el enlace correcto ''this''
-
No se utiliza ''this'' en absoluto, lo que significa un código claro que es mucho menos propenso a errores
-
La interfaz pública es clara y está separada de la implementación como proxy de los métodos privados.
-
permite una composición fácil
con esto puedes hacer:
function Counter() {
// public interface
const proxy = {
advance, // advance counter and get new value
reset, // reset value
value // get value
}
// private variables and methods
let count=0;
function advance() {
return ++count;
}
function reset(newCount) {
count=(newCount || 0);
}
function value() {
return count;
}
return proxy;
}
let counter=Counter.New();
console.log(counter instanceof Counter); // true
counter.reset(100);
console.log(''Counter next = ''+counter.advance()); // 101
console.log(Object.getOwnPropertyNames(counter)); // ["advance", "reset", "value"]
<script src="https://cdn.rawgit.com/kofifus/New/7987670c/new.js"></script>
vea New para el código y ejemplos más elaborados que incluyen constructor y composición
Siempre puedes usar funciones normales:
function myPrivateFunction() {
console.log("My property: " + this.prop);
}
class MyClass() {
constructor() {
this.prop = "myProp";
myPrivateFunction.bind(this)();
}
}
new MyClass(); // ''My property: myProp''