深入理解原型链
原型链和原型对象是js的核心,js以原型链的形式,保证函数或对象中的方法、属性可以向下传递,按照面向对象的说法,这就是继承。而js通过原型链才得以实现函数或对象的继承,那么下面我们就来聊一聊js中的原型链。👇
函数的prototype
1)函数的prototype属性
-
每个函数都有一个prototype属性,它默认指向一个Object空对象(即称为:原型对象)
注意:这里的空对象是指:没有我们指定的属性和方法 -
原型对象中有一个属性constructor,它指向函数对象
2)给原型对象添加属性(一般都是方法)
- 作用:函数的所有实例对象自动拥有原型中的属性(方法)
<script>
// 每个函数都有一个prototype属性,它默认指向一个Object空对象(即称为:原型对象)
console.log(Date.prototype,typeof Date.prototype );
//自己定义一个函数
function Fun() {
}
console.log(Fun.prototype); //默认指向一个Object空对象(没有我们的属性)
// 原型对象中有一个属性constructor,它指向函数对象
console.log(Date.prototype.constructor===Date);
console.log(Fun.prototype.constructor===Fun);
// 给原型对象添加属性(一般是方法)===> 实例对象恺英访问
Fun.prototype.test = function () {
console.log('test()');
}
// 创建实例对象
var fun = new Fun()
fun.test()
</script>
显式原型和隐式原型
-
每个函数function都有一个prototype,即显示原型;
-
每个实例对象都有一个
__proto__,可称为隐式原型;
每个对象都有
__proto__,它是隐式原型属性,指向了创建该对象的构造函数原型。由于js中是没有类的概念,而为了实现继承,通过__proto__将对象和原型联系起来组成原型链,就可以让对象访问到不属于自己的属性。
- 对象的隐式原型的值为其对应构造函数的显式原型的值;
<!---->
<script>
// 定义构造函数
function Fn(){
// 内部语句:this.prototype = {}
}
// 1.每个函数function都有一个prototype,即显示原型属性,默认指向,一个空对象Object
console.log(Fn.prototype);
// 2.每个实例对象都有一个__proto__,可称为隐式原型
// 创建实例对象
var fn = new Fn() // 内部语句:this.__proto__ = Fn.prototype
console.log(fn.__proto__);
// 3.对象的隐式原型的值为其对应构造函数的显示原型的值
console.log(Fn.prototype===fn.__proto__);
// 给原型添加方法
Fn.prototype.test = function(){
console.log('test()');
}
// 通过实例调用原型的方法
fn.test()
</script>
- 内存结构图:
5)总结:
- 函数的prototype属性:在定义函数时自动添加的,默认值是一个空Object对象;
- 对象的
__proto__属性: 在创建对象时自动添加的,默认值为构造函数的prototype属性值 - 程序员的直接操作显示原型,但不能直接操作隐式原型(ES6之前)
原型链
1)原型链
- 访问一个对象属性时,先在自身属性中查找,找到就返回
- 如果没有,再沿着
__proto__这条链向上查找,找到就返回 - 如果最终没有找到,就返回undefined
- 别名:隐式原型链
- 作用:查找对象的属性(方法)
<script>
function Fn(){
this.test1 = function(){
console.log('test1');
}
}
console.log(Fn.prototype);
Fn.prototype.test2 = function(){
console.log('test2()');
}
var fn = new Fn()
fn.test1()
fn.test2()
console.log(fn.toString());
console.log(fn.test3);
fn.test3()
</script>
2)构造函数/原型/实体对象的关系(图解)
3)构造函数/原型/实体对象的关系2(图解)
// 1.函数的显示原型指向的对象默认时Object实例对象(但object不满足)
console.log(Fn.prototype instanceof Object);//true
console.log(Object.prototype instanceof Object); //false
console.log(Function.prototype instanceof Object);//true
// 2.所有函数都是Function的实例(包含Function)
console.log(Function.__proto__===Function.prototype);//true
// 3.Object的原型对象是原型链的尽头
console.log(Object.prototype.__proto__);//null
再次理解