Para criar uma classe JavaScript com um método público, eu faria algo como:
function Restaurant() {}
Restaurant.prototype.buy_food = function(){
// something here
}
Restaurant.prototype.use_restroom = function(){
// something here
}
Dessa forma, os usuários da minha classe podem:
var restaurant = new Restaurant();
restaurant.buy_food();
restaurant.use_restroom();
Como crio um método privado que pode ser chamado pelos métodos buy_food
e use_restroom
, mas não externamente pelos usuários da classe?
Em outras palavras, quero que minha implementação de método seja capaz de:
Restaurant.prototype.use_restroom = function() {
this.private_stuff();
}
Mas isso não deve funcionar:
var r = new Restaurant();
r.private_stuff();
Como eu defino private_stuff
como um método privado para que ambos sejam verdadeiros?
Eu li o artigo de Doug Crockford algumas vezes, mas não parece que métodos "privados" possam ser chamados por métodos públicos e métodos "privilegiados" podem ser chamados externamente.
javascript
oop
private-methods
Wayne Kao
fonte
fonte
Usando a função de auto-chamada e chamada
O JavaScript usa protótipos e não possui classes (ou métodos), como linguagens orientadas a objetos. Um desenvolvedor de JavaScript precisa pensar em JavaScript.
Citação da Wikipedia:
Solução usando uma função de auto-chamada e a função de chamada para chamar o "método" privado:
A função de chamada nos permite chamar a função privada com o contexto apropriado (
this
).Mais simples com o Node.js
Se você estiver usando o node.js , não precisará do IIFE, pois poderá aproveitar o sistema de carregamento do módulo :
Carregue o arquivo:
(experimental) ES7 com o operador Bind
O operador de ligação
::
é uma proposta ECMAScript e é implementada no Babel ( estágio 0 ).Carregue o arquivo:
fonte
.call
peça.f()
em javascript (não no momento)..call
) e pouca memória (nenhuma função na instância)? Isso existe?Você pode simular métodos privados como este:
Mais informações sobre esta técnica aqui: http://webreflection.blogspot.com/2008/04/natural-javascript-private-methods.html
fonte
Nessas situações, quando você possui uma API pública e deseja métodos / propriedades públicas e privadas, sempre uso o Padrão do Módulo. Esse padrão foi popularizado na biblioteca YUI e os detalhes podem ser encontrados aqui:
http://yuiblog.com/blog/2007/06/12/module-pattern/
É realmente simples e fácil para outros desenvolvedores compreenderem. Para um exemplo simples:
fonte
aPrivateMethod = function() { MYLIB.aPublicProperty}
:?Aqui está a classe que eu criei para entender o que Douglas Crockford sugeriu em seu site Membros Particulares em JavaScript
fonte
that
é usado em vez dethis
evitar problemas de escopo, quando funções são vinculadas a um objeto diferente. Aqui, você está armazenandothis
emthat
e nunca usá-lo novamente, o que é o mesmo que não fazê-lo em tudo. Você deve mudarthis
comthat
toda asConstructor
funções internas (não declaração de métodos). Seemployee
forapply
ed oucall
ed de alguma forma, esses métodos podem ser lançados, poisthis
serão incorretamente vinculados.Eu conjurei isso: EDIT: Na verdade, alguém se vinculou a uma solução idêntica. Duh!
fonte
var getAwayVehicle = new Car(100);
onde100
está a velocidade e você deseja alertar a velocidade. Obrigado!var Car = function(speed) { this.speed = speed; }
e `return {constructor: Car, ...`Penso que essas questões surgem repetidas vezes devido à falta de entendimento dos fechamentos. Сlosures é a coisa mais importante em JS. Todo programador de JS precisa sentir a essência disso.
1. Antes de tudo, precisamos criar um escopo separado (fechamento).
2. Nesta área, podemos fazer o que quisermos. E ninguém saberá sobre isso.
3. Para que o mundo conheça nossa classe de restaurantes, precisamos devolvê-la do fechamento.
4. No final, temos:
5. Além disso, essa abordagem tem potencial para herança e modelagem
Espero que isso ajude alguém a entender melhor esse assunto
fonte
Pessoalmente, prefiro o seguinte padrão para criar classes em JavaScript:
Como você pode ver, ele permite definir propriedades de classe e propriedades de instância, cada uma das quais pode ser pública e privada.
Demo
Veja também este violino .
fonte
Todo esse fechamento custará você. Certifique-se de testar as implicações de velocidade, especialmente no IE. Você descobrirá que está melhor com uma convenção de nomenclatura. Ainda existem muitos usuários corporativos da Web que são forçados a usar o IE6 ...
fonte
Não seja tão detalhado. É Javascript. Use uma convenção de nomenclatura .
Após anos trabalhando nas classes es6, comecei recentemente a trabalhar em um projeto es5 (usando o requireJS, que já é muito detalhado). Estive repetidamente todas as estratégias mencionadas aqui e tudo basicamente se resume a usar uma convenção de nomenclatura :
private
. Outros desenvolvedores que inserem Javascript saberão disso com antecedência. Portanto, uma simples convenção de nomenclatura é mais que suficiente. Uma convenção de nomenclatura simples de prefixo com um sublinhado resolve o problema das propriedades particulares e dos métodos privados.my-tooltip.js
fonte
define
,constructor
ee a própria estrutura. Embora eu concorde principalmente com a resposta, comecei a trabalhar com JS com muita influência no POO e até pulei muito cedo para o TS, pois tinha experiência anterior em C #. Acho que tenho que desaprender essas coisas e entender o paradigma de prototipagem / procedimento. (votado, btw)Você pode fazer isso agora com métodos privados es10 . Você só precisa adicionar um
#
antes do nome do método.fonte
Pegue qualquer uma das soluções que seguem o padrão privado ou privilegiado de Crockford . Por exemplo:
Nos casos em que o invasor não tem direito de "execução" no contexto JS, ele não tem como acessar campos ou métodos "públicos" ou "privados". Caso o invasor tenha esse acesso, ele pode executar este procedimento:
Observe que o código acima é genérico para toda a privacidade do tipo construtor. Falhará com algumas das soluções aqui, mas deve ficar claro que praticamente todas as soluções baseadas em fechamento podem ser quebradas dessa maneira com
replace()
parâmetros diferentes .Após isso ser executado, qualquer objeto criado
new Foo()
terá umeval
método que pode ser chamado para retornar ou alterar valores ou métodos definidos no fechamento do construtor, por exemplo:O único problema que vejo com isso é que ele não funcionará nos casos em que há apenas uma instância e é criada no carregamento. Porém, não há razão para definir um protótipo e, nesse caso, o atacante pode simplesmente recriar o objeto em vez do construtor, desde que ele possua uma maneira de transmitir os mesmos parâmetros (por exemplo, eles são constantes ou calculados a partir dos valores disponíveis).
Na minha opinião, isso praticamente torna a solução de Crockford inútil. Como a "privacidade" é facilmente quebrada, as desvantagens de sua solução (legibilidade e manutenção reduzidas, desempenho reduzido, aumento de memória) tornam o método baseado em protótipo "sem privacidade" a melhor escolha.
Eu costumo usar sublinhados principais para marcar
__private
e_protected
métodos e campos (estilo Perl), mas a idéia de ter privacidade em JavaScript mostra apenas como é uma linguagem incompreendida.Portanto, eu discordo de Crockford, exceto por sua primeira frase.
Então, como você obtém privacidade real em JS? Coloque tudo o que é necessário para ser privado no lado do servidor e use o JS para fazer chamadas AJAX.
fonte
(function () {allMyStuff}());
para não expor nada global.f.eval('nameOfVariable')
quando você não sabe o que'nameOfVariable'
é ...A apoteose do padrão do módulo: o padrão revelador do módulo
Uma pequena extensão elegante para um padrão muito robusto.
fonte
Se você deseja que toda a gama de funções públicas e privadas com a capacidade de funções públicas acessem funções privadas, código de layout para um objeto como este:
fonte
new MyObject
, o protótipo deMyObject
é substituído pelos mesmos valores..prototype
interior do construtor.Semelhante ao georgebrock, mas um pouco menos detalhado (IMHO) Algum problema em fazê-lo dessa maneira? (Eu não vi isso em lugar nenhum)
edit: eu percebi que isso é meio inútil, já que toda instanciação independente tem sua própria cópia dos métodos públicos, prejudicando o uso do protótipo.
fonte
Aqui está o que eu mais gostei até agora em relação a métodos / membros privados / públicos e instanciação em javascript:
aqui está o artigo: http://www.sefol.com/?p=1090
e aqui está o exemplo:
JSFiddle: http://jsfiddle.net/northkildonan/kopj3dt3/1/
fonte
O padrão do módulo está correto na maioria dos casos. Mas se você tiver milhares de instâncias, as classes economizam memória. Se economizar memória é uma preocupação e seus objetos contêm uma pequena quantidade de dados privados, mas possuem muitas funções públicas, convém que todas as funções públicas residam no protótipo. Para economizar memória.
Isto é o que eu vim com:
O objeto
priv
contém propriedades particulares. É acessível através da função públicagetPriv()
, mas essa função retorna, afalse
menos que você a passesecret
, e isso é conhecido apenas dentro do fechamento principal.fonte
Que tal isso?
A pesquisa de variáveis privadas é impossível fora do escopo da função imediata. Não há duplicação de funções, economizando memória.
A desvantagem é que a pesquisa de variáveis privadas é desajeitada
privateVars[this.id].cooked
e ridícula ao digitar. Há também uma variável "id" extra.fonte
Restaurant
comoundefined
porque você não está retornando nada da função anônima.Restaurant
foi coletada no lixo, seus valores permanecem dentroprivateVars
. AWeakMap
pode ser um bom substituto para oArray
neste caso.Agrupe todo o código na Função Anônima: Então, todas as funções serão privadas, APENAS funções anexadas ao
window
objeto:Usa isto :
FIDDLE
fonte
Eu prefiro armazenar dados privados em um associado
WeakMap
. Isso permite que você mantenha seus métodos públicos no protótipo ao qual eles pertencem. Essa parece ser a maneira mais eficiente de lidar com esse problema para um grande número de objetos.fonte
Funções privadas não podem acessar as variáveis públicas usando o padrão do módulo
fonte
Como todo mundo estava postando aqui seu próprio código, eu também vou fazer isso ...
Eu gosto de Crockford porque ele introduziu padrões reais de orientação a objetos em Javascript. Mas ele também apresentou um novo mal-entendido, o "aquele".
Então, por que ele está usando "isso = isso"? Não tem nada a ver com funções privadas. Tem a ver com funções internas!
Porque, de acordo com Crockford, este é um código de buggy:
Então ele sugeriu fazer isso:
Então, como eu disse, tenho certeza de que Crockford estava errado na explicação sobre isso e isso (mas seu código está certamente correto). Ou ele estava apenas enganando o mundo Javascript, para saber quem está copiando seu código? Não sei ... Não sou nerd de navegadores; D
EDITAR
Ah, é disso que se trata: O que significa 'var that = this;' significa em JavaScript?
Então, Crockie estava realmente errado com a explicação dele ... mas certo com o código dele, então ele ainda é um cara legal. :))
fonte
Em geral, adicionei o objeto privado _ temporariamente ao objeto. Você precisa abrir a privacidade de forma explícita no "Construtor de poder" para o método Se você chamar o método a partir do protótipo, poderá sobrescrever o método do protótipo
Torne um método público acessível no "Construtor de energia": (ctx é o contexto do objeto)
Agora eu tenho esse openPrivacy:
fonte
Isto é o que eu descobri:
Precisa de uma classe de código de açúcar que você pode encontrar aqui . Também suporta coisas protegidas, herança, virtuais e estáticas ...
fonte
https://github.com/nooning/JSClass
fonte
Criei uma nova ferramenta para permitir que você tenha métodos privados verdadeiros no protótipo https://github.com/TremayneChrist/ProtectJS
Exemplo:
fonte
_private
método?Você precisa encerrar sua função construtora real, onde pode definir seus métodos particulares. Para alterar os dados das instâncias por meio desses métodos particulares, é necessário dar a eles "isso" com eles, como argumento de função ou chamando essa função com .apply (this):
fonte
new Restaurant
terão seu própriorestaurant
construtor, e o "protótipo" é totalmente abusado.Eu sei que é um pouco tarde demais, mas e quanto a isso?
fonte
Já existem muitas respostas para essa pergunta, mas nada atendeu às minhas necessidades. Então, eu vim com minha própria solução, espero que seja útil para alguém:
Como você pode ver, este sistema funciona ao usar esse tipo de classe em javascript. Tanto quanto eu descobri, nenhum dos métodos comentados acima o fez.
fonte
Consulte esta resposta para obter uma solução 'classe' limpa e simples com uma interface pública e privada e suporte para composição
fonte