As an example, take objects. C++ has objects. Smalltalk does too. Also Java and C# and a whole lot of other languages. However, all of the objects in those languages are bound together by sharing a single class.
Javascript and Lua don't share that requirement. They're still object-based (you have entities which hide implementation and expose functionality), but object's don't necessarily share a common class. In fact, an object in these languages can (and often does) have no class at all.
Further still, some languages have object-like things. Erlang, for example, allows you to create processes. Processes can send messages to each other. Processes can even have private data (since a process is just a function, and functions can always have local variables, processes can have private data). Is this an object? I think so!
Some languages even give you object-like functionality in even stranger ways. Take purely functional languages like Lisp (or Scheme) or ML. These languages let you create "closures". A closure is a function that exists within (is closed to) an environment. In Javascript (not a functional language, but one which supports closures):
function make_add(left_addend) {
var f = function(right_addend) {
return left_addend + right_addend;
}
//At this point, f is bound to left_addend. Whatever
//we passed in as left_addend is now known by f.
//We can return f, and it will correctly remember
//the value of left_addend.
return f;
}
var add10 = make_add(10);
var add1000 = make_add(1000);
print_to_console(add10(5));
print_to_console(add10(50));
print_to_console(add1000(5));
print_to_console(add1000(50));
15
60
1005
1050
Why is this cool? Well, we have effectively created an entity which has private data. We could go a step further and make 'f' into some sort of dispatch method. It could take, as its first parameter, an operation. So, perhaps we could have this:
function make_number(value) {
var f = function(operation) {
if (operation == "add") {
return make_number(value + arguments[1]);
} else if (operation == "sub") {
return make_number(value - arguments[1]);
} else if (operation == "toString") {
return value;
} else {
return null;
}
}
var number10 = make_number(10);
var number1000 = make_number(1000);
print_to_console(number10("add", 5)("toString"));
print_to_console(number10("sub", 50)("toString"));
print_to_console(number1000("sub", 5)("toString"));
print_to_console(number1000("add", 50)("toString"));
15
-40
995
1050
Not too pretty, but it should work. Object-oriented programming in functional languages. Who knew?