Showdown del codice: Ruby vs Javascript

Ruby e JavaScript stanno per andare testa a testa. Entrambi questi linguaggi di scripting sono tipizzati in modo dinamico e supportano la programmazione orientata agli oggetti. Esamineremo le loro differenze o somiglianze attraverso alcune delle loro caratteristiche più comuni.

Dichiarazione di non responsabilità: qui stiamo solo esaminando la sintassi JavaScript ES6 moderna.

Foto di Pramote Polyamate su 500px

Interpolazione di stringhe

Nella programmazione al computer, l'interpolazione di stringhe è il processo di iniezione del valore di una variabile o di un'espressione in una stringa letterale.

In Ruby, questo si chiama, hai indovinato, interpolazione di stringhe.

Rubino:

first_name = "Martin"
last_name = "Riggs"
mette "Ciao, sono # {first_name} # {last_name}."

In Javascript, la stessa cosa può essere raggiunta con i template letterali.

JavaScript:

const firstName = 'Martin';
const lastName = 'Riggs';
console.log (`Ciao, sono $ {firstName} $ {lastName} .`);

Metodi e funzioni

Wikipedia spiega che, nella programmazione per computer, una subroutine è una sequenza di istruzioni del programma che esegue un compito specifico, impacchettata come un'unità. Questa unità può quindi essere utilizzata nei programmi ovunque si debba eseguire quel particolare compito.

In diversi linguaggi di programmazione, un sottoprogramma può essere chiamato una procedura, una funzione, una routine, un metodo o un sottoprogramma.

Per poter essere utilizzate, queste subroutine devono essere prima definite e poi chiamate. In Ruby, sono conosciuti come metodi e in JavaScript, sono chiamati funzioni.

Rubino:

def full_name (first_name, last_name)
  "# {first_name.capitalize} # {last_name.capitalize}"
fine
mette full_name ("beatrix", "kiddo")

JavaScript:

funzione fullName (firstName, lastName) {
  return `$ {firstName.capitalize ()} $ {lastName.capitalize ()}`;
};
console.log (fullName ("beatrix", "kiddo"));

Se stai eseguendo gli esempi sopra, probabilmente avrai notato che l'esempio JavaScript non funziona, ma genera un errore: TypeError Uncaught: firstName.capitalize non è una funzione!

Questo perché JavaScript non definisce nativamente una funzione di maiuscolo. Ruby ha molti metodi idiomatici pratici e accurati come #capitalize che sono davvero convenienti. Per far funzionare l'esempio sopra, dovremo utilizzare la catena di prototipi (patch di scimmia) sull'oggetto String di JavaScript:

String.prototype.capitalize = function () {
  restituisce this.charAt (0) .toUpperCase () + this.slice (1);
}

blocchi

In Ruby, i blocchi sono sostanzialmente blocchi di codice senza nome che possono essere passati e richiamati dai metodi interni. Molti dei metodi di oggetti incorporati in Ruby accettano blocchi e questi sono un modo conveniente per modificare il modo in cui tali metodi si comportano.

Rubino:

timer di def
  start_time = Time.now
  mette "Blocco in esecuzione ..."
  
  dare la precedenza
  mette "Finito!"
  end_time = Time.now - start_time
  "Tempo di esecuzione: # {end_time}"
fine
mette il timer {(0..10000000) .sort}

Ehi, JavaScript non ha blocchi, quindi l'implementazione di cui sopra non è possibile e il confronto è sciocco! O è? Le funzioni JavaScript possono accettare le funzioni di callback come argomenti e se pensiamo ai blocchi di Ruby come a metodi anonimi possiamo ottenere un risultato simile.

JavaScript:

timer funzione (richiamata) {
  const startTime = new Date (). getTime ();
  console.log ("Running callback ...");
  
  richiama();
  console.log ( "Finito!");
  const endTime = new Date (). getTime ();
  return `Tempo di esecuzione: $ {endTime - startTime}`;
};
timer (() => Array.from (Array (10000000) .keys ()). sort ());

Nota: a differenza di Ruby, JavaScript non ha un oggetto Range incorporato. Array.from (Number) .keys () sopra restituisce una matrice da 0 a numero.

Iterazioni idiomatiche

Ruby è noto per avere degli iteratori idiomatici molto carini da scorrere tra gli array (e altri Enumerabili o strutture iterative).

Rubino:

names = ["Tango", "Cash", "Dalton", "Riggs"]
names.each do | name |
  mette il nome
fine

Con ES6, iterare attraverso un array in JavaScript diventa un gioco da ragazzi:

JavaScript:

const names = ['Tango', 'Cash', 'Dalton', 'Riggs'];
names.forEach (name => console.log (name));

Nota: la funzione Javascript forEach può anche accedere all'indice dell'elemento. In Ruby, utilizzeremmo un iteratore diverso per quello chiamato each_with_index.

Classi ed eredità di classe

Nella programmazione orientata agli oggetti, le classi sono modelli di codice per la creazione di oggetti, che forniscono valori per stato (proprietà o attributi dell'oggetto) e implementano il comportamento (come getter e setter per leggere e scrivere tali proprietà o attributi).

Rubino:

veicolo di classe
  def inizializza (nome, tipo)
    @nome = nome
    @type = type
  fine
  nome def
    @nome
  fine
  tipo di def
    @genere
  fine
fine
class Car 
diablo = Car.new ("Lamborghini")
mette diablo.name
mette diablo.type

JavaScript:

veicolo di classe {
 
  costruttore (nome, tipo) {
    this.name = name;
    this.type = type;
  }
 
  getName () {
    restituire this.name;
  }
 
  getType () {
    restituisce this.type;
  }
 
}
auto di classe estende il veicolo {
 
  costruttore (nome) {
    super (nome, "macchina");
  }
}
const diablo = new Car ('Lamborghini');
console.log (diablo.getName ());
console.log (diablo.getType ());

Nota: Nell'esempio sopra, la classe Veicolo Ruby verrebbe in genere implementata con un lettore di attributi per creare i metodi getter per le variabili di istanza. Ho scelto di non utilizzare un lettore di attributi in modo da avere un aspetto più simile all'implementazione JavaScript.

destrutturazione

JavaScript moderno ha introdotto questa cosa davvero interessante chiamata destrutturazione, in cui è possibile assegnare elementi all'interno di matrici o oggetti a variabili con una sintassi concisa.

JavaScript:

firstName, lastName = 'James Bond'.split ();
console.log (`My name is $ {lastName}, $ {firstName} $ {lastName}`);

Sicuramente non puoi farlo in Ruby!

Rubino:

first_name, last_name = "James Bond" .split
mette "Il mio nome è # {last_name}, # {first_name} # {last_name}"

Nota: mentre possiamo distruggere le matrici in Ruby come facciamo in JavaScript, non esiste un Ruby equivalente a distruggere direttamente gli hash.

Operatore di diffusione

Il moderno JavaScript ha inoltre introdotto l'operatore spread che consente di espandere espressioni iterabili laddove sono previsti zero o più argomenti o elementi.

JavaScript:

somma delle funzioni (x, y, z) {
  ritorna x + y + z;
};
numeri const = [1, 2, 3];
console.log (somma (... numeri);
[a, b, ... rest] = [10, 20, 30, 40, 50];
console.log (a);
console.log (b);
console.log (riposo); // resto è un array!

In Ruby, abbiamo l'operatore splat per questo.

Rubino:

somma somma (x, y, z)
  x + y + z
fine
numeri = [1, 2, 3]
mette la somma (* numeri)
a, * resto, b = [10, 20, 30, 40, 50]
mette a
mette b
mette resto # resto è un array!

Nota: probabilmente avrai notato che in Ruby * il resto è tra le altre variabili. Questo è l'operatore splat che può essere posizionato ovunque tra le variabili. In JavaScript, l'operatore di diffusione deve arrivare per ultimo.

Ruby ha anche l'operatore double splat ** per fare la stessa cosa sugli hash. La specifica JavaScript ES2018 introduce anche l'operatore spread su oggetti.

Parola finale

Come probabilmente avrai capito, entrambe le lingue non sono poi così diverse e, con ES6, JavaScript è diventato sempre più piacevole da scrivere. Certo, JavaScript è la lingua del browser e il suo ciclo di eventi fornisce un comportamento asincrono. D'altra parte, Ruby ha strumenti molto potenti per fare metaprogrammazione ed è amato per la sua sintassi idiomatica. Alla fine, penso che sia utile imparare e conoscere entrambi, poiché spesso la conoscenza di un linguaggio di programmazione ti darà idee su come codificare o affrontare un determinato problema in un altro.