Un Booleano JS con proprietà personalizzate è una cattiva pratica?

41

In JS puoi restituire un booleano con proprietà personalizzate. Per esempio. quando Modernizr testa il supporto video restituisce true o false ma il Booleano restituito (Bool è l'oggetto di prima classe in JS) ha proprietà che specificano quali formati sono supportati. All'inizio mi ha sorpreso un po ', ma poi ho iniziato ad apprezzare l'idea e ho iniziato a chiedermi perché sembra essere usato con parsimonia?

Sembra un modo elegante per gestire tutti quegli scenari in cui fondamentalmente vuoi sapere se qualcosa è vero o falso, ma potresti essere interessato ad alcune informazioni aggiuntive che puoi definire senza definire un oggetto di reso personalizzato o usando un callback funzione pronta ad accettare più parametri. In questo modo si mantiene una firma di funzione molto universale senza compromettere la capacità di restituire dati più complessi.

Ci sono 3 argomenti contro di esso che posso immaginare:

  1. È un po 'insolito / inaspettato quando è probabilmente meglio che qualsiasi interfaccia sia chiara e non complicata.
  2. Questo potrebbe essere un argomento per uomo di paglia, ma con il suo essere un caso marginale posso immaginare che si ritorca silenziosamente in qualche ottimizzatore JS, ugificatore, VM o dopo una piccola modifica delle specifiche della lingua ecc.
  3. C'è un modo migliore - conciso, chiaro e comune - di fare esattamente lo stesso.

Quindi la mia domanda è: ci sono motivi validi per evitare l'uso di booleani con proprietà aggiuntive? Sono un trucco o una sorpresa?

Avviso di colpi di scena.

Sopra è la domanda originale in piena gloria. Come hanno sottolineato entrambi Matthew Crumley e senevoldsen, si basa su una premessa falsa (falsa?). Nella raffinata tradizione JS ciò che Modernizr fa è un trucco di linguaggio e uno sporco. Si riduce a JS con un bool primitivo che se impostato su false rimarrà falso anche dopo aver cercato di aggiungere oggetti (che fallisce silenziosamente) e un oggetto booleano che può avere oggetti di scena personalizzati ma essere un oggetto è sempre vero. Modernizr restituisce un valore booleano falso o un vero oggetto booleano.

La mia domanda originale presuppone che il trucco funzioni in modo diverso e quindi le risposte più popolari affrontano aspetti (perfettamente validi) degli standard di codifica. Comunque trovo che le risposte smascherano l'intero trucco più utile (e anche gli argomenti finali contro l'uso del metodo), quindi accetto uno di loro. Grazie a tutti i partecipanti!

    
posta konrad 09.01.2017 - 05:57
fonte

9 risposte

38

Oltre ai principi generali di progettazione, come la singola responsabilità, e meno sorprendentemente, c'è una ragione specifica di JavaScript che non è una buona idea: c'è un'enorme differenza tra un boolean e Boolean in JavaScript che lo impedisce dal lavorare nel caso generale.

boolean è un tipo primitivo, non un oggetto e non può avere proprietà personalizzate. Espressioni come true.toString() funzionano perché dietro le quinte, diventa (new Boolean(true)).toString() .

Boolean (con una B maiuscola) è un oggetto, ma ha pochissimi buoni usi, e essendo usato come boolean non è sicuramente uno di questi. Il motivo è che ogni Boolean è "true", indipendentemente dal suo valore , perché tutti gli oggetti vengono convertiti in true in un contesto booleano. Ad esempio, prova questo:

var answer = new Boolean(false);
if (answer) {
  console.log("That was unexpected.");
}

Quindi, in generale, non c'è modo di aggiungere proprietà a un valore booleano in JavaScript che consente comunque di comportarsi in modo logico. Modernizr può farla franca perché l'unica aggiunta di proprietà a valori "veri", che tipo di lavoro come ti aspetteresti (cioè lavorano in istruzioni if). Se il video non è supportato, Modernizr.video sarà un boolean effettivo (con il valore false ) e non può avere proprietà aggiunte ad esso.

    
risposta data 09.01.2017 - 17:55
fonte
59

Congratulazioni, hai scoperto degli oggetti. La ragione per non farlo è chiamata principio di minimo stupore . Essere sorpresi da un design non è una buona cosa.

Non c'è niente di sbagliato nel raggruppare insieme queste informazioni, ma perché dovresti nasconderlo in un Bool? Mettilo in qualcosa che ti aspetti di avere tutte queste informazioni. Bool incluso.

    
risposta data 09.01.2017 - 06:43
fonte
16

L'argomento principale su cui mi oppongo è il principio di responsabilità singola , un booleano dovrebbe dire solo se qualcosa è true o false , non perché o come o qualsiasi altra cosa. È mia ferma convinzione e pratica che altri oggetti debbano essere usati per comunicare quella o qualsiasi altra informazione.

    
risposta data 09.01.2017 - 06:44
fonte
10

Poiché l'intera ragione è chiamata valore booleano è il fatto che sia vero o falso, non mi piace l'idea, in quanto praticamente indebolisci il suo intero scopo da wikipedia

In computer science, the Boolean data type is a data type, having two values (usually denoted true and false), intended to represent the truth values of logic and Boolean algebra.

(il mio audace)

    
risposta data 09.01.2017 - 11:51
fonte
2

Solo perché puoi non significa che dovresti, in JS puoi praticamente collegare le proprietà a qualsiasi oggetto (inclusi Booleans)

Com'è una brutta cosa?

Da un lato, puoi allegare più dati irrilevanti a un booleano (secondo il tuo esempio), qualcosa che un altro sviluppatore non si aspetterebbe, perché dovrebbe esserci ?! i bool sono solo per veri e falsi.

Un punto di riferimento è di allegare alcune utili proprietà utili che possono aiutarti ad affrontare il valore booleano ( Java lo fa ).

Ad esempio, puoi associare una funzione che converte il valore booleano in una stringa, un flag dirty che diventa true se il valore è stato modificato, osservatori e callback di eventi che possono essere attivati quando il valore viene modificato ecc.

but the returned Boolean (Bool is first class object in JS) has properties specifying what formats are supported

Sembra qualcosa che non dovrebbe essere memorizzato in un booleano, ma piuttosto usando un Set di booleani, o un Set di proprietà con i booleani al loro interno. Penso che un approccio migliore sarebbe quello di restituire un oggetto con tutti i formati e i dettagli del supporto.

{
    isSomethingSupported: true,
    isSomethingElseSupported: false,
    ....
}
    
risposta data 09.01.2017 - 11:18
fonte
1

Non puoi creare booleani con proprietà personalizzate in JavaScript. Il seguente errore (almeno in FF):

    var x = false;
    x.foo = "bar";
    console.log(x.foo);

Puoi usare, o ereditare da Boolean, ma come dice Matthew Crumley dà risultati diversi. Boolean è di tipo Object . Quando JS ha bisogno del valore booleano di un'espressione, converte utilizzando la funzione di specifica ToBoolean , che impone che per Object s il risultato sia sempre true . Quindi il valore new Boolean(false) valuta true ! Puoi verificarlo in questo esempio: link .

L'unica ragione per cui funziona per Modernizr è incidentale. Creano solo un oggetto Boolean quando la condizione è vera. Quando valutano false, restituiscono solo% ordinario% co_de. Funziona quindi perché restituiscono solo false oggetti quando il risultato è true, e mai quando è falso.

    
risposta data 09.01.2017 - 18:39
fonte
1

Capisco che il contesto sia cambiato, ma mi piacerebbe rispondere alla domanda originale che ho letto usando JS come esempio, ma non limitato a solo JS.

L'aggiunta di proprietà a un booleano, non sarebbe un problema SE le proprietà avevano qualcosa a che fare con il vero / falso, non con la variabile che contiene il valore. Ad esempio, l'aggiunta di un metodo toYesNoString andrebbe bene, l'aggiunta di un numeroOfChildren a un valore hasChildren non lo è, e nessuno dei due interrogheràSenza studentePassato. Non c'è molto che si possa aggiungere a un booleano, oltre a varie ripetizioni di stringhe, l'unica proprietà che posso pensare che abbia senso è originalExpression. Ma aggiungerlo non è necessariamente una cattiva idea in teoria.

    
risposta data 20.01.2017 - 03:17
fonte
0

Se guardo il codice, non si tratta di fornire proprietà booleane personalizzate, ma di un metodo che ha metodi di restituzione con diverse firme.

Se è falso, ottieni una primitiva falsa e se è vera restituisce un oggetto che per definizione viene interpretato come true in javascript.

Quindi, a mio parere, la tua domanda non dovrebbe essere se sia una buona idea fornire proprietà booleane personalizzate, ma se sia una buona idea avere metodi con più firme di ritorno.

    
risposta data 09.01.2017 - 19:06
fonte
0

Nell'esempio indicato, potresti solo restituire un array di tutti i formati video supportati?

  • Un array vuoto significa "nessun video formati supportati", il che significa "nessun video supportato".
  • Altrimenti, se è supportato qualsiasi formato video, è ovviamente supportato video in generale.

Direi almeno che usare l'array è un po 'meno sorprendente di avere "booleani personalizzati".

In Javascript, un array vuoto è addirittura considerato falsy , mentre un array non vuoto è vero , quindi con un po 'di fortuna potresti passare agli array e tutto funzionerebbe come prima modifica No, stupido per aver pensato di poter ricordare la veridicità degli oggetti in JavaScript: P

    
risposta data 09.01.2017 - 18:22
fonte

Leggi altre domande sui tag