Executando verificação de segurança...
1

"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í!

Carregando publicação patrocinada...
3

objetos (equivalente aos dicts do python, por exemplo), funções, arrays e o null. Tudo mais NÃO É considerado um objeto pela linguagem.

Hmm, será?

Na especificação da linguagem tem uma seção chamada "Fundamental Objects" que possui 5 sub-seções:

  • Object Objects
  • Function Objects
  • Boolean Objects
  • Symbol Objects
  • Error Objects

Os dois primeiros são os que vc já citou (objetos e funções), mas depois temos booleanos, símbolos e erros (exceções, como ReferenceError, etc).

E depois tem outras seções que tratam de tipos diferentes, mas que também são chamados de "objetos":

Sem contar o Array, Map, Set, JSON, etc, todos esses são chamados de "Objects" pela especificação.


Só pra citar um exemplo, tanto /a/ instanceof Object quanto [] instanceof Object retornam true (a regex e o array são subtipos de Object).

No caso de números e strings é um pouco mais confuso: new String('a') instanceof Object é true mas 'a' instanceof Object é false. Isso é porque existem os tipos primitivos (string, números, etc), que não possuem métodos, mas quando vc tenta usar algum método (como 'abc'.includes('a')) é feito um auto-boxing automático para a classe wrapper equivalente (mais detalhes aqui).

De qualquer forma, veja que existem vários tipos que são sub-tipos de Object, e não se restringem aos que vc citou...


Inclusive, dá para definir propriedades em uma string, mas temos que usar o wrapper:

var x = new String('abc');
x.prop = 'oi';
console.log(x.prop); // oi

Se fizermos x = 'abc' aí não funciona porque estamos usando o primitivo, e para definição de propriedades não é feito o auto-boxing. Mas enfim, String é um objeto também. E o mesmo vale para Number, Boolean, etc.

2

A resposta está perfeita, como sempre.

Só para dar uma pitada de sal, de fato tudo que é dado (não códigos ou qualquer outras coisa, que poucas linguagens são assim, ou seja, que tratam tudo como dados, em geral chamadas de homoicônicas) é objeto.

Claro que não é no sentido do que fala a postagem original e ao seu reply, que está correto em separar o "objeto composto" e que é um Object, do objeto simples (muitas vezes chamados de escalar, mesmo quando não é).

A questão do null é diferente, e ele é um tipo simples que pode ser atribuído onde cabe um "objeto". No JS é o que é, o mais importante é o efeito geral.

Quis trazer alguns links para dar mais luz ao assunto que é interessante para quem quer saber a computação além da superfície. Tem muito mais informações para pesquisar. Entender como as coisas são é melhor do que só intuir.

Obrigado por essa contribuição.

Farei algo que muitos pedem para aprender a programar corretamente, gratuitamente. Para saber quando, me segue nas suas plataformas preferidas. Quase não as uso, não terá infindas notificações (links aqui).

2

Bem lembrado. De fato, "objeto" é um termo bem amplo, e cada linguagem acaba usando-o de maneiras diferentes (o mesmo vale para "primitivo"). Em muitos casos, nada tem a ver com orientação a objeto - só pra citar um exemplo, em C o termo "objeto" é definido como uma "região de armazenamento de dados do ambiente de execução, cujo conteúdo pode representar valores".


Outro detalhe: null é listado com um dos valores primitivos. E na especificação da linguagem não há nenhuma menção a um "objeto null" (como há para os outros tipos listados, como "Number Object", "Boolean Object", etc, mas nada de "Null Object"). Então o null não é um objeto?

Mas então porque typeof null retorna "object"? Simples, porque a especificação da linguagem diz que é assim:

5. If val is null, return "object".

Se algo é null, então typeof algo deve retornar "object". Ou seja, a especificação não tem nenhuma menção a "Null Object" (como tem para todos os subtipos de Object), mas ao mesmo tempo define que o tipo de null é "object".

1

Sim, eu ignorei os wrappers e objetos que podem ser instanciados com new porque já caem na ideia do "objeto que lembra o dict do python". Incluir os conceitos de prototype e da emulação de classe/objeto que existem em JS levaria a discussão pra outro lado. O regex foi o único que esqueci mesmo, valeu por lembrar! Vou fazer um edit comentando isso.

2

E só pra ser chato, vc pode criar arrays e funções com new :-)

var x = new Function('a', 'b', 'return a + b');
console.log(x(1, 2)); // 3

x.prop = 'oi';
console.log(x.prop); // oi

var y = new Array(1, 2, 3);
console.log(y); // [ 1, 2, 3 ]

y.prop = 'oi';
console.log(y.prop); // oi

Mas entendi o que vc quis dizer :-)

1

Sim hehe vlw por comentar! Já editei pra deixar mais claro. Minha ideia original era trazer pra discussão apenas os valores que comumente imaginamos como objetos em JS (sintaxe chave-valor), independente do extenso e confuso sistema de classes Object do JS e da emulação que ela faz do sistema OOP com os prototypes. Talvez justamente por isso que se espalhou essa ideia do "tudo em JS é um objeto".

"Ahh, javascript... such a messy language..."
2

Sim, eu ignorei os wrappers e objetos que podem ser instanciados com new porque já caem na ideia do "objeto que lembra o dict do python"

Eu não tinha entendido assim. O que eu entendi de "objeto que lembra o dict do python" são aqueles que vc cria com a sintaxe { chave: valor } (e não com new).

Fica a sugestão de deixar esse ponto mais claro :-)

1
3
1
2
0

Não entendi, nome roubado?

JS era liveScript era o Scheme no navegador.
Ai veio a parceria com a Sun, tudo mudou.

O nome, o jeito da linguagem era funcional passou a ser OOP
Mas um OOP diferente pq não poderia ser 100% igual java.
Tinha que ser um irmão mais novo do "poderoso" java.
E um oop com prototypes pq era melhor pra memoria na época!