JavaScript的原型与原型链的重要性不必多说,一步步看,JavaScript原型与原型链秒懂!
- 原型(prototype)
- 显式原型与隐式原型
- 原型链
原型
牢记❗
- 每一个函数都有一个prototype属性,指向空的Object对象(没有我们添加的属性)
- 原型对象中有一个属性constructor,它指向函数对象
代码验证及图解
// 创建一个函数
function Fun() {}
// 每一个函数都有一个prototype属性,指向空的Object对象
console.log(Fun.prototype)
// 原型对象中有一个属性constructor,它指向函数对象
console.log(Fun.prototype.constructor === Fun.prototype) // true
总结:构造函数和引用对象是相互引用的关系
显示原型与隐式原型
牢记❗
- 每一个函数都有prototype,称为显式原型
- 每一个实例对象都有一个__proto__,称为隐式原型
- 对象的隐式原型的值为其构造函数的显式原型
代码验证
- 每一个函数都有一个prototype属性,指向空的Object对象,代表了什么?
- 对象的隐式原型的值为其构造函数的显式原型,代表了什么?
// 1.每一个函数都有prototype,指向空的Object对象
function Fn() {} // 代表了内部代码 this.prototype = {};
var fn = new Fn() // 代表了内部代码 this.__proto__ = Fn.prototype
// 2.对象的隐式原型的值为其构造函数的显式原型
console.log(fn.__proto__ === Fn.prototype) // true
案例代码及图解
function Fn() {}
var fn = new Fn()
Fn.prototype.test = function(){
console.log('hello')
}
fn.text() // hello
案例中fn.text()是如何得到的?
总结:对象的隐式原型的值为其构造函数的显式原型❗❗❗
原型链
理解原型链,其实就是将上面牢记❗的内容进行运用
案例代码及图解
function Fn() {
this.test1 = function() {
console.log('test()1')
}
}
Fn.prototype.test2 = function() {
console.log('test()2')
}
fn.test1() // test()1
fn.test2() // test()2
fn.test3() // Uncaught TypeError: fn.test3 is not a function
上述代码为什么test1、test2可以运行,test3不可以呢?
略微有一点复杂?,接下来慢慢拆解,然后再回过头看这张图就简单了
// 当创建函数時内存的结构是怎么样的
function Fn() {}
再用代码来验证图吧!
function Fn(){}
// 1.验证Object函数的原型对象就是尽头了吗?
console.log(Object.prototype.__proto__ === null) // true
// 2.Fn的原型对象真的是Object的实例吗?
console.log(Fn.prototype instanceof Object) // true
回答为什么test1、和test2找的到
- test1是在Fn实例对象中所以找得到
- test2是在Fn的原型对象中(它沿着实例对象的__proto__找到其构造函数❗(这里构造函数就是Fn,因为是new Fn)❗的原型对象)
- test3是找不到,因为找到尽头都没有
牢记❗ - 函数的显示原型指向的对象默认是空Object实例对象(Object不满足)
- 所有函数都是Function的实例(包括它本身Function)
- Object的原型对象是原型链的尽头
总结:心中牢记每个函数都有prototype,每个实例都有__protot__。并且__protot__的值是其构造函数的显式原型