JavaScript关于原型链的总结
JavaScript关于原型链的总结
一、原型属性
- 函数的prototype属性
- 每个函数都有一个prototype属性, 它默认指向一个Object空对象(即称为: 原型对象)
- 原型对象中有一个属性constructor, 它指向函数对象
- 给原型对象添加属性(一般都是方法)
- 作用: 函数的所有实例对象自动拥有原型中的属性(方法)
当在创建每一个函数时,解析器会向函数添加一个属性prototype(这就是所谓的原型对象)
- 显示原型与隐式原型
函数=>构造函数
对象=>实例对象
1)每个函数function都有一个prototype,即显式原型
Fn.prototype
2)每个实例对象都有一个__proto__,可称为隐式原型
let fn =new Fn()
fn.__proto__
3)对象的隐式原型的值对应构造函数的显式原型的值
fn.__proto__ = Fn.prototype
fn.__proto__ === Fn.prototype
4)在定义函数的时候,会自动添加一个prototype属性,默认值是一个空Object对象
function Fn() {}
this.prototype = {}
5)当创建实例对象的时候,会自动添加__proto__属性,默认值是=>prototype属性值
function Fn() {}
// 创建一个实例对象
var fn = new Fn()
fn.__proto__ = Fn.prototype // 默认值是=> prototype的值
6)程序员能直接操作显式原型, 但不能直接操作隐式原型(ES6之前)
// 定义构造函数
function Fn() {
// 内部语句:this.prototype = {}
}
var fn = new Fn() // 内部语句:fn.__proto__ = Fn.prototype
// 给prototype添加test方法
Fn.prototype.test = function () {
console.log('test()')
}
// 通过实例调用原型的方法
fn.test()

二、原型链
- 原型链(图解)
-
访问一个对象的属性时,
-
先在自身属性**(实例对象属性)**中查找,找到返回
-
如果没有, 再沿着
__proto__这条链向上查找, 找到返回 -
如果最终没找到, 返回undefined
-
别名: 隐式原型链
-
作用: 查找对象的属性(方法)
function Fn() {// 内部语句:this.prototype = {}
this.test1 = function () {
console.log('test1()')
}
}
Fn.prototype.test2 = function () {
console.log('test2()')
}
var fn = new Fn() // 内部语句:fn.__proto__ = Fn.prototype
// 通过实例调用原型的方法
fn.test1()
fn.test2()
fn.test3()

总结:
- 在
Object空对象里同样也有一个隐式原型,在找下去就会找到Object原型对象,而Object原型对象同样也有一个隐式原型,只不过他的值为null
- 构造函数/原型/实体对象的关系(图解)
- o1,o1:有一个隐式原型属性(
__ proto __)他指向Object的原型对象(Object.prototype)
var o1 = new Object();
var o2 = {};

- 构造函数/原型/实体对象的关系2(图解)
-
1)首先创建一个函数,他有一个显示原型属性(
Foo.prototype),默认是空的Object对象- 此时是构造函数
function Foo(){ }
-
2)为什么
Foo构造函数的隐式原型指向Function的显示原型?let Foo = new Function()Foo函数是Function()的实例对象,因此Foo的__proto__指向Function的显示原型属性。- 根据定义=>当创建实例对象时,实例对象的隐式原型对应构造函数的显示原型
-
**TIP:所有函数都有一个隐式原型属性(
__ proto __)指向大写Funcion的显示原型属性(Funcion.prototype)**具体为什么?看下面。 -
3)为什么
Function的隐式原型指向自身的显示原型?Function = new Function()- 因为
Function是Function()的实例对象,那么隐式原型必定指向显示原型 
-
4)我们继续看图:
let Object = new Function()- 我创建了一个新的函数名为Object,他的隐式原型同样也会指向
Function的显示原型,因为他也是New Function产生的 
最关键是要掌握一点:
构造函数隐式原型指向Function的显示原型(也可以说指向Function的构造函数的显示原型)
而构造函数实例化后:实例对象隐式原型=>构造函数的显示原型
实例对象的隐式原型=构造函数的显示原型
-
5)总结:
-
所有构造函数都是通过
new Function产生 -
所有函数的构造函数的
__proto__都是指向Function的显示原型,因为都是由new Function产生 -
这里做个小总结:所有的函数对象都是
Function函数的实例对象,因此函数的隐性原型属性都是一样的。然后这些函数都有各自自己的显性原型属性,他们自己创建的实例对象,与其隐性原型属性地址值相等。
-
function Foo(){ }
let Foo = new Function()
Function = new Function()

4)函数的显示原型指向的对象默认是空Object实例对象(但Object不满足)
console.log(Fn.prototype instanceof Object) // true
console.log(Object.prototype instanceof Object) // false
console.log(Function.prototype instanceof Object) // true
5)所有函数都是Function的实例(包含Function)
console.log(Function.__proto__===Function.prototype)
6)Object的原型对象是原型链尽头
console.log(Object.prototype.__proto__) // null
三、instanceof
表达式:A instanceof B
判断B函数的显示原型对象是否在A对象的原型链上(A原型链是否存在B的显示原型)
A是一个实例对象
B是一个构造函数对象
- 例一
-
function Foo() { } var f1 = new Foo(); console.log(f1 instanceof Foo);// true console.log(f1 instanceof Object); // true -
f1是实例对象,而Foo是构造函数对象 -
函数的实例对象默认是一个空的Object对象,然后又因为(实例对象的隐式原型=构造函数的显示原型),所以:如图


- 例二
console.log(Object instanceof Function);// true
console.log(Object instanceof Object);// true
console.log(Function instanceof Function);// true
console.log(Function instanceof Object);// true
function Foo() {}
console.log(Object instanceof Foo);// false
1)Function作为构造函数看显示原型,Object作为实例对象看隐式原型,其他就没什么好说了,自行看图。

function Foo() { }
var f1 = new Foo();
let o1 = new Object()
console.log(f1 instanceof Foo);// true
console.log(f1 instanceof Object); // true

原型链的总结
-
显示原型与隐式原型
- 显示原型:
prototype - 隐式原型:
__proto__ - 构造函数有:显示原型
- 构造函数隐式原型永远指向Function显示原型
- 实例对象有:隐式原型
- 显示原型:
-
访问属性
- 访问一个属性的时候,是先在自身属性找,找不到就沿着隐式原型向上找,最终找不到会返回undefined
- 小提示:我们是在沿着实例对象上找。
-
定理1:
Object的原型对象是原型链的尽头。 -
定理2:实例对象的隐式原型永远等于构造函数显示原型。
- 红线是显示原型,显示原型指向显示原型属性。
- 紫线是隐式原型,而显示原型指向哪里,隐式原型就会跟着指向哪里。

-
定理3:构造函数的显示原型属性默认是空的Object实例对象。(除了Object)
-
定理4:所有函数对象都是
Function的实例对象。(包括Function) -
定理4:所有构造函数的隐式原型必定指向
Function的显示原型。 -
定理5:
Object隐式原型指向Function的显示原型。
本文总结了JavaScript中的原型链概念,包括原型属性、原型链的工作原理和`instanceof`操作符的使用。每个函数都有`prototype`属性,指向一个Object空对象,实例对象可以通过隐式原型访问构造函数的原型。当查找对象属性时,会沿着原型链向上搜索。`instanceof`用于判断一个对象的原型链上是否存在某个构造函数的原型。

被折叠的 条评论
为什么被折叠?



