一、显式原型、隐式原型

  • 显式原型prototype,是每个函数被定义时,系统自动添加的
  • 隐式原型__proto__,是实例对象创建时,自动添加的,其值 === 其原型的显式对象prototype ```javascript function Person() {}; var p = Person();

Person.prototype; // 显式原型 p.proto; // 隐式原型 p.__proto === Person.prototype; // true,两者相等,指向同一个 object 实例对象

  1. ---
  2. <a name="GY6Cf"></a>
  3. ### 二、原型链的基本用法
  4. - 只有**函数(构造器)**才拥有 ` prototype `属性,如下的 ` Peoson() `
  5. ```javascript
  6. function Person() {};
  7. let p = new Person();
  • 原型是一片公共存储区域,对原型的修改,会对所有变量生效,如下 ```javascript Person.a = 1; // 直接对 Person 函数对象进行修改,无法对原型链生效 console.log(p.a); // undefined

Person.prototype.b = 2; // 用 prototype 即可修改原型链 console.log(p.b); // 2

p.c = 1; console.log(Person.c); // undefined

p.proto.d = 1; console.log(Person.prototype.d); // 1


- **任何对象**都拥有 ` __proto__ ` 属性,表示该对象的原型,换个角度说,某个对象的 ` __proto__ `===该对象原型的 ` prototype `,参考如下代码,输出 true,因为 Person 为 p 的原型

```javascript
console.log(p.__proto__ === Person.prototype);  // true,
  • 对象的原型并不是其父亲,即 p.__proto__ !== Person,而为 p.__proto__ === Person.protptype ,参考如下代码,因为用 p.__proto__.d 所修改的为 p 所指向的原型 Person.prototype,而 Person 本身并不会包含 d 这个属性

    p.__proto__.d = 2;      // 
    console.log(Person.d);  // undefined
    console.log(Person.prototype.d); // 2
    
  • 任何原型都是 Object的实例” 空 “对象,但 Object 自身的原型 除外,(Object 自身的原型为所有原型链的终点) ```javascript function A() {};

console.log(A.prototype instanceof Object); // true console.log(Function.prototype instanceof Object); // true console.log(Object.prototype instanceof Object); // false


- 所有函数都是 ` Function `的实例,包括它自身(_即 Function = new Function() 是自己创造自己_)
```javascript
function A() {};

console.log(A.prototype === A.__proto__);               // false
console.log(Function.prototype === Function.__proto__); // true
// 即:Function 的 显式原型 和 隐式原型 是相等的

三、图的解释

121853AD-2964-4A39-B44D-5660EF203019.jpeg

  • 一切原型链的尽头,为 Object.prototype,即为 Object的原型
  • toString()等方法,是存在 Object.prototype中的
  • 对象自己也可以有很多属性,这些属性无法通过 对象.prototype.属性来获取,只能通过 对象.属性 来获取
  • Object原型的隐式原型 __proto__ === null

四、instanceof

** A instanceof B **:A的隐式原型 若在 B的显式原型 上,则返回 true(B只有一层,A可有多层)

function A() {};

console.log(Object instanceof Object);
console.log(Object instanceof Function);
console.log(Function instanceof Object);
console.log(Function instanceof Function);  // 前四个都是 true

console.log(Object instanceof A);           // false

_** **_**console.log(Object instanceof Object) 解释**

  1. Object 实际上是 function Obejct(),因此 instanceof 左端的隐式原型Object.__proto__ === Function.prototype,右端的显式原型Object.prototype
  2. 又因为 Function.prototype所有原型默认都为 Object 的空对象,除了 Object的原型,其包含了一些系统自带的方法如toString())的隐式原型Object.prototype这是一切原型链的终点),故输出为true

    console.log(Object instanceof Object);    // true
    

    五、易混淆点

    1、显式对象的指针改变时,隐式对象不会跟着变

    如下,当 Person.prototype指向(区分改变值)被人为改变时,其实例对象 Jack的隐式原型 __proto__不会跟着改变,因此输出会异常
    Bob被声明时,会采用 Person最新的显式对象,因此能正常输出

     function Person() {};
    
     Person.prototype.n = 1;
    
     let Jack = new Person();
     Person.prototype = {
         n: 222,
         m: 333
     }
     let Bob = new Person();
    
     console.log(Jack.n, Jack.m, Bob.n, Bob.m);  // 1, undefined, 222, 333
    

    2、读取时会自动读取原型上的属性,赋值时不会,只要自己没有,就直接赋值给自己

    具体参考《继承》一、原型链继承 *关于继承属性的注意点

继承