해당 글은 도서 "코어 자바스크립트" 바탕으로 작성한 글입니다.
개인적으로 정리한 글이므로 틀린 부분이 있을 수 있습니다!
자바스크립트로 개발을 하거나 알고리즘 문제를 풀 때 항상 들었던 의문이 있다. 왜 JS는 인스턴스로 메소드를 바로 호출하지 않고 Object.values(), Object.keys()와 같이 앞에 Object를 붙여서 호출하는 것일까?
결론부터 말하자면, 이는 자바스크립트가 프로토타입 기반 언어이기 때문이다. 이를 이해하기 위해 먼저 프로토타입이 무엇인지부터 알아보자.
prototype은 '객체'이다. 그런데 우리는 prototype과 __proto__를 구분해야한다(ES6부터 __proto__는 호환성 유지를 위해 남겨진 것이므로 직접적인 사용은 피하도록 하자).
var obj = new Object();
위와 같이 생성자 함수를 호출해 인스턴스를 하나 만들 경우, obj라는 인스턴스에는 Object의 prototype을 참조하는 __proto__가 자동으로 부여된다. 즉, 인스턴스의 __proto__를 통해 생성자 함수의 메소드나 프로퍼티에 접근이 가능하다는 것이다.
실제로 콘솔에서 다음과 같이 Object로 인스턴스를 생성해 디렉터리 구조를 출력해보면, obj1이 Object를 원형으로 하는 인스턴스이고, Object.prototype의 메소드와 프로퍼티들을 확인할 수 있다.

이때 __proto__를 열어서 확인해보면, Object.prototype와 그 구조가 동일함을 알 수 있다.

즉, obj1.__proto__가 Object.prototype을 참조하기 때문에, 둘은 동일함을 알 수 있다.

여기서 우리가 알아야할 것은, __proto__는 생략이 가능하다는 것이다. 이 말인 즉슨 우리가 인스턴스의 메소드를 호출했던 것이 사실은 인스턴스.__proto__의 메소드를 호출했다는 것이다.
var arr = [1, 2];
arr.push(3); // arr(.__proto__).push(3);
그런데 위 배열 구조를 콘솔에 출력해보면 이상한 점을 한가지 발견할 수 있다. 바로 __proto__ 안에 __proto__가 또 있다는 것이다.


이를 열어보니 Object.prototype이 등장하고 있다. 그 이유에 대해 책은 다음과 같이 말하고 있다.
바로 prototype 객체가 '객체'이기 때문입니다. 기본적으로 모든 객체의
__proto___에는 Object.prototype이 연결됩니다.
다시 말해서 Object.prototype은 모든 객체의 조상이라는 것이다. arr로 Object.prototype의 메소드를 사용할 수 있었던 것도 이 때문이다.
arr.hasOwnProperty(2); // arr(.__proto__)(.__proto__).hasOwnProperty(2);
이러한 반복적인 구조를 우리는 '프로토타입 체인'이라고 부른다.
위의 개념들을 다 이해했다면 obj.values()가 아닌, Object.values(obj)로 불러야하는 이유를 이해하는 데에는 무리가 없을 것이다. 만약 Object 객체에서만 사용할 메소드를 prototype 내부에 정의해놓았다면, Object.prototype은 모든 객체의 조상이므로, 다른 데이터 타입(Array, String, 등)으로도 접근이 가능해진다. 따라서, obj(.__proto__).values()가 아닌, 즉 Object.prototype.values(obj)가 아닌, Object.values(obj)로 하여금 메소드를 호출해야했던 것이다.
결론적으로, 자바스크립트가 여느 객체지향 언어들처럼 인스턴스.메소드()와 같이 호출하지 못했던 이유는 바로 이 Object를 조상으로 삼는 프로토타입의 특성에 있었음을 알 수 있다. 메소드 앞의 인스턴스가 곧 this가 되는 객체지향 언어들과는 달리, JS가 this를 고집하지 않고 인자로 주입해 인스턴스를 연결한 이유도 여기에 있었다.