所有东西都是对象
在 JS 中,除了 null, undefined 以外所有数据类型都是对象
普通对象
就是我们常识中的对象,常见的普通对象如下:
- 字面量对象 
{} - 字面量字符串 
"abc" - 字面量数值 
123 NaNfoo = new Foo(),foo就是普通对象
函数对象
函数就是函数对象
function Foo() {}Foo 就是一个函数对象
函数对象同时也是普通对象,函数对象是普通对象的超集,特点之一就是拥有原型 prototype
普通对象是函数对象的实例
所有普通对象都持有 __proto__ 属性,该属性指向构建该实例的函数对象的原型
以普通对象里的例子为例子:
- 字面量对象 
{},Object的实例 
({}).__proto__ === Object.prototype; // true- 字面量字符串 
"abc",String的实例 
"abc".__proto__ === String.prototype; // true- 字面量数值 
123,Number的实例(NaN也是) 
(123).__proto__ === Number.prototype; // true
NaN.__proto__ === Number.prototype; // truefoo = new Foo(),foo就是普通对象,是Foo的实例
function Foo() {}
new Foo().__proto__ === Foo.prototype; // true所有函数对象都是 Function 的实例
Function 本身也是函数对象,所以它是它自身的实例
function Foo() {}
Foo.__proto__ === Function.prototype; // true
String.__proto__ === Function.prototype; //true
Object.__proto__ === Function.prototype; //true
Function.__proto__ === Function.prototype; // true所有原型都是 Object 的实例
function Foo() {}
Foo.prototype.__proto__ === Object.prototype; // true
String.prototype.__proto__ === Object.prototype; // true
Function.prototype.__proto__ === Object.prototype; // true但 Object 自身的原型并不是任何函数对象的实例,因此
Object.prototype.__proto__; // null原型链
使用 __proto__ 串起原型,就是原型链了,顶端即 Object.prototype.__proto__,为 null
instanceof
instanceof 用于判断对象类型,其机制正是在原型链上寻找原型:
target.__proto__target.__proto__.__proto__- 以此类推
 
所有对象都是 Object 类型
function Foo() {};
Array instanceof Object; // true
Function instanceof Object; // true
Foo instanceof Object; // true因为函数对象 Function 是 Object 的派生实例:
Function.__proto__.__proto__ === Object.prototype; // true且实例都派生自 Function,那么肯定也派生自 Object
实例本身不存在的属性,会尝试在原型上找
当我们访问实例属性时,如果实例上没找到,会在构造实例的函数对象的原型上找
下面的 foo 实例本身并没有 toString,但是读取时可以读到,这是因为 Object.prototype 上有这个属性
function Foo() {}
var foo = new Foo();
Object.hasOwn(foo, 'toString'); // false
foo.toString // ƒ toString() { [native code] }具体查找逻辑就是沿着原型链一路往上找
foo.__proto__ -> foo.__proto__.__proto__ -> … -> Object.prototype.__proto__
经典老图
