一、显式原型、隐式原型
- 显式原型:
prototype
,是每个函数被定义时,系统自动添加的 - 隐式原型:
__proto__
,是实例对象创建时,自动添加的,其值 === 其原型的显式对象prototype
```javascript function Person() {}; var p = Person();
Person.prototype; // 显式原型 p.proto; // 隐式原型 p.__proto === Person.prototype; // true,两者相等,指向同一个 object 实例对象
---
<a name="GY6Cf"></a>
### 二、原型链的基本用法
- 只有**函数(构造器)**才拥有 ` prototype `属性,如下的 ` Peoson() `
```javascript
function Person() {};
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 的 显式原型 和 隐式原型 是相等的
三、图的解释
- 一切原型链的尽头,为
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) 解释**
:
- Object 实际上是 function Obejct(),因此
instanceof
左端的隐式原型为Object.__proto__ === Function.prototype
,右端的显式原型为Object.prototype
又因为
Function.prototype
(所有原型默认都为 Object 的空对象,除了 Object的原型,其包含了一些系统自带的方法如toString())的隐式原型为Object.prototype
(这是一切原型链的终点),故输出为trueconsole.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、读取时会自动读取原型上的属性,赋值时不会,只要自己没有,就直接赋值给自己
具体参考《继承》一、原型链继承 *关于继承属性的注意点