Tipizzazione debole
- Stringhe
- Numeri (integer e reali)
- Boolean
- Undefined
- Null
Ogni altra cosa è un oggetto: classi, funzioni, array, RegExp. Gli oggetti vengono passati come referenze, mentre i primitivi sono passati per valore.
== esegue il casting automatico del tipo, mentre === non lo fa.
'a' === new String('a') *// false*
'a' === new String('a').toString() *// true*
'a' == new String('a') *// true*
Buffer – Tipo di dato super di Node.js
Buffer è un tipo di dato, un’aggiunta di Node.js ai 5 primitivi e agli oggetti generici(array, funzioni ecc…). Sono come archivi per dati estremamente efficienti.
Notazione letterale degli oggetti
const car = {
color: "green",
type: "suv",
owner: {...},
drive: funtion(){...}
}
C’è la possibilità di estendere un altro oggetto, definire dinamicamente i campi, invocare super() ed usare una sintassi più concisa per le funzioni.
Funzioni
Le funzioni in Node.js sono degli oggetti e possono avere anche proprietà/attributi.
Definire/Creare una funzione
Espressione con un nome:
function f() {
console.log('Hi')
return true
}
Espressione di una funzione anonima:
const f = function(){
console.log('Hi')
return true
}
Arrow function (introdotta da ES6):
const f = () => {
console.log('Hi')
return true
}
Return implicito:
è possibile usare il return implicitamente se la dichiarazione della funzione è su una sola riga.
f = (a,b) => a+b
Array
Sono anch’essi degli oggetti, che dispongono di alcuni metodi speciali.
let arr = []
let arr2 = [1,"Hi", {a:2}, ()=>{console.log('ciao')}]
let arr3 = new Array()
let arr4 = new Array(1,24,6)
arr2[3]() // boo
Natura Prototipale
In Javascript non esistono classi perché gli oggetti ereditano direttamente da altri oggetti. Questo è detta eredità prototipale. In JavaScript esistono pochi pattern di eredità:
- Classica
- Pseudoclassica
- Funzionale
let user = function(ops) {
return {firstName: ops.FirstName || 'John',
lastName: ops.lastName || 'Doe',
email: ops.email || 'test@test.com',
name: function() { return this.firstName + lastName}
}
}
let agency = function(ops) {
ops = ops || {}
var agency = user(ops)
agency.consumers = ops.consumers || 0
agency.isAgency = true
return agency
}
Con l’introduzione delle classi in ES6, la classe può essere estesa, definita e istanziata con extends, class e new.
class baseModel {
constructor(options = {}, data = []) {
//costruttore della classe
this.name = 'Base'
this.url = 'https://mapodesign.com'
this.data = data
this.options = options
}
getName(){
//metodo della classe
console.log(`Class name: ${this.name}`)
}
}
Da qui si può creare una nuova classe usando la classe base. La nuova classe erediterà tutte le funzionalità di quella base, più altri elementi:
class AccountModel extends baseModel {
constructor(options, data) {
super({private:true}, ['7349457','6824975'])
//chiama il metodo parent con il super
this.name = 'Accont Model'
this.url += '/accounts/'
}
get accountsData(){ // attributo getter calcolato
// ... esegui XHR
return this.data
}
}
let account = new AccountModel(5)
accounts.getName()
console.log('Data is %s', accounts.accountsData)
Il risultato sarà:
Class Name: Account Model
Data is %s 7349457,6824975
Convenzioni
Punti e virgola
Quasi tutte le dicharazioni in JavaScript e Node devono terminare con punto e virgola. Tuttavia i motori JavaScript dispongono di una funzione di inserimento automatico.
CamelCase e Nomi
In nomi di variabili e sono da inserire con il CamelCase, tranne i nomi delle classi; è possibile anche usare _ e $ prima o allinterno dei nomi.
Identazione
Spazi vuoti
Usati per convenzione prima e dopo un simbolo. Mentre nelle invocazioni e nella funzione anonima non si utilizzano spazio prima delle parentesi arr.push(1)
oppure function() {}