Isso era um assunto controverso nos anos 80.
Em 87, Peter Wegner, publicou um artigo na OOPSLA que resolveu a questão (pelo menos entre aqueles que concordam com o Wegner)
Para uma linguagem ser Orientada a Objetos ela precisa segundo Wegner
ser baseada em objetos, ou seja, deve ser fácil programar objetos que encapsulam dados e operações;
ser baseadas em classes, ou seja, cada objeto pertence a (ou é fabricado a partir de) uma classe; e +
permitir herança, ou seja, deve ser fácil agrupar classes em hierarquias de subclasses e superclasses.
Outros estudiosos (chatos?) acrescentam outros itens à lista: (eu não concordo - Wegner)
enlace dinâmico, tardio (late binding)
A linguagem Self é uma grande exceção entre as linguagens claramente orientada a objetos: ela não possui classes.
JS e Lua tem coletores de lixo e não são baseadas em classes.
Para Wegner essas não são linguagem OOP.
Rust também entra na discussão. Ela possui structs e permite criar funções associadas a elas. Então, apesar de não ter o nome classe, e separar atributos (variáveis) de comportamento (métodos/funções), ela possui algo bem parecido ao conceito de classe, podendo ser considerado orientado a objetos por isso. Porém, não tem herança, então por essa definição não seria orientada a objetos. Apesar de eu já ter visto ideias que deveria-se usar mais interfaces e menos heranças, e como Rust tem traits, que podem ser considerada uma interface com mais recursos, e inclusive que lembram bastante herança, como todo
Eq
também é umPartialEq
, volta a discussão.