系列文章推荐
JavaScript原型与原型链(基础篇)
JavaScript原型与原型链(进阶篇)
JavaScript原型与原型链(总结篇)
1 构造函数和实例对象
构造函数的prototype
属性为其实例化对象的原型__proto__
:
function Cat(name, age) {
this.name = name
this.age = age
}
const kat = new Cat('kat', 2)
console.log(kat.__proto__ === Cat.prototype) // true
2 构造函数属性constructor
constructor
属性用于通过实例对象或原型获取其构造函数:
function Cat(name, age) {
this.name = name
this.age = age
}
const kat = new Cat('kat', 2)
console.log(kat.__proto__.constructor === Cat) // true
console.log(Cat.prototype.constructor === Cat) // true
注意:kat.constructor === Cat
也是成立的,虽然constructor
属性不在实例对象kat
上,但是在访问属性时若实例本身不存在,则会在原型链上寻找,所以能在kat.__proto__
上找到constructor
属性。
3 Object
Object
构造函数有两大特点:
- 所有构造函数的原型对象都是
Object
构造函数的实例对象,即满足Func.prototype.__proto__ === Object.prototype
,其中Func
代指所有构造函数; Object.prototype.__proto__
为原型链的终点,即Object.prototype.__proto__ === null
;
function Cat(name, age) {
this.name = name
this.age = age
}
const kat = new Cat('kat', 2)
console.log(kat.__proto__.__proto__ === Object.prototype) // true
// kat.__proto__ === Cat.prototype
console.log(Cat.prototype.__proto__ === Object.prototype) // true
console.log(Object.prototype.__proto__ === null) // true
4 Function
Function
构造函数有两大特点:
- 所有构造函数都是由
Function
构造函数实例化而来:Func.__proto__ === Function.prototype
,其中Func
代指所有构造函数; Function
自身是构造函数,且自身又是自身构造函数的实例化对象:Function.__proto__ === Function.prototype
。
function Cat(name, age) {
this.name = name
this.age = age
}
console.log(Cat.__proto__ === Function.prototype) // true
console.log(Function.__proto__ === Function.prototype) // true
5 Object
和Function
Object
和Function
两个内置构造函数区别与其他内置构造函数,有如下特点,以下所有的运算结果都为true
:
Function instanceof Object
Object instanceof Function
Function instanceof Function
Object instanceof Object
根据上述结论还能推导及验证出如下关系:
Function.__proto__.__proto__ === Object.prototype
Object.__proto__ === Function.prototype
Function.__proto__ === Function.prototype
Object.__proto__.__proto__ === Object.prototype
6 function anonymous()
所有构造函数的原型都为function anonymous()
,由于所有函数都是由Function
构造函数实例化而来,那么最简单的获取function anonymous()
的方式为Function.prototype
,满足如下关系:
function Cat() {}
console.log(Cat.__proto__ === Function.prototype) // true
console.log(Object.__proto__ === Function.prototype) // true
console.log(Array.__proto__ === Function.prototype) // true
console.log(Number.__proto__ === Function.prototype) // true
console.log(Function.__proto__ === Function.prototype) // true
7 __proto__
和prototype
__proto__
用于实例对象获取原型,prototype
用于构造函数获取其实例对象的原型,两者关系如下:
function Cat() {}
const kat = new Cat()
console.log(kat.__proto__ === Cat.prototype) // true
console.log(Cat.__proto__ === Function.prototype) // true
console.log(Function.__proto__ === Function.prototype) // true
对于__proto__
,有如下几种情况:
- 对于一般实例对象来说,如实例对象
kat
,kat.__proto__
得到的是其构造函数Cat
的prototype
属性; - 对于一般构造函数来说,如构造函数
Cat
,Cat.__proto__
得到的是其构造函数Function
的prototype
属性,且这个值是确定的,为function anonymous()
; - 对于构造函数
Function
来说,Function.__proto__
得到的是其构造函数Function
的prototype
属性,且这个值是确定的,为function anonymous()
。
对于prototype
,有如下几种情况:
- 对于一般实例对象来说,如实例对象
kat
,kat.prototype
得到的是undefined
,即一般实例对象是没有prototype
属性的,只有构造函数才存在prototype
属性; - 对于一般构造函数来说,如构造函数
Cat
,Cat.prototype
得到的是由该构造函数实例化对象的原型,在本例子中为kat.__proto__
; - 对于构造函数
Function
来说,Function.prototype
得到的是由该构造函数实例化对象的原型Function.__proto__
,因为Function
自身是构造函数,且自身又是自身构造函数的实例化对象,所以Function.__proto__ === Function.prototype
。
8 其他内置构造函数
JavaScript中的内置构造函数只有Function
和Object
是特殊的,除去Function
和Object
以外的其他构造函数,如Number
、String
和Array
等等,都可以当作普通构造函数来看待。