"Em JS tudo é um objeto"
Não.
Só passando pra ajudar os mais novos que provavelmente já ouviram isso em algum lugar, ou mesmo os mais velhos que manteram a ideia na cabeça. Em JS, existem apenas 4 tipos que são, na verdade, sub-tipos da classe Object: objetos (e aqui englobo qualquer valor que esteja conforme a sintaxe { chave: valor }
, independente da proveniência - wrapper, new
, etc), funções, arrays e o null
. Tudo mais NÃO É considerado um objeto pela linguagem.
Atualmente, a única maneira (infelizmente) de checar se um valor é um "objeto" sem recorrer a bibliotecas é:
const isObject = val =>
(typeof val == 'object') &&
(typeof val != 'function') &&
(!Array.isArray(val)) &&
(val !== null)
Então sim, é possível definir propriedades para funções e arrays:
const arr = [1, 2, 3]
console.log(arr.length) // 3
console.log(arr.prop) // undefined
arr.prop = "oi"
console.log(arr.prop) // "oi"
quando você cria um array, o que o JS faz é simplesmente armazenar os valores em propriedades usando os índices como prop: [1, 2, 3] == { 0: 1, 1: 2, 2: 3, length: 3, ... }
function fn() {
// ...
}
console.log(fn.name) // "fn"
console.log(fn.prop) // undefined
fn.prop = "oi"
console.log(fn.prop) // "oi"
"Ué mas por que null
também é um objeto?" Pois é, boa pergunta. É um bug já há muito conhecido que não é (nem nunca será) corrigido pelo simples fato de que muitos sites existentes utilizam este exploit - soltar uma nova ES alterando esse comportamento quebraria muita página por aí!