The three basic concepts on which object-oriented languages are built are encapsulation, inheritance, and polymorphism. An object-oriented language should provide you, the programmer, with easy tools with which to execute these three concepts.
Encapsulation means making an object's internal workings invisible to the programmer. Instead of being a drawback, this invisibility is, in fact, a benefit. When the code that is used to perform operations within an object is hidden, the author of the object's code has the ability to change how the object performs operations at any time without adversely affecting every program that was written using that object. For an example, Array objects contain a method called sort() that will sort all of the elements in an array. Imagine for a moment that this method was written using a slow, linear sort algorithm. If the designer of the Array object decided later on down the line to switch to the quicker, binary sort algorithm that was presented in Chapter 4, he could simply replace the old algorithm with the new one. Because both algorithms perform the same operation, the programmer who then uses the Array object would never know the switch ever took place. This allows the built-in functions of a language to be improved upon without compromising preexisting programs written in it.
Inheritance is one of the most important aspects of object-oriented programming. Inheritance allows a program to reuse preexisting object types without rewriting their functionality from scratch. For an example, let's examine the Array object type. If you wanted to have the functionality of a linked list, but did not have the Array.prototype property or did not want to use it, you could create a new class called List that extended the Array class. The new List class would have all of the functionality of the original Array class, but then you could add more functionality into it automatically.
Polymorphism is the most complicated of the three must-haves for an object-oriented language. The basis of this idea states that every class should be able to handle different data types. For example, if you write a Shape class that has a single method, draw(), and then create two more classes, Square and Circle, which implement the draw() method, invoking the draw() method on any Shape class (be it a Square or Circle object) should cause the operations needed to draw the proper shape to be executed.