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
的显示原型。