原型与原型链小结

什么是原型

所有函数都有的一个属性,这个属性的值是一个对象,这个对象叫作原型对象。
这个属性是prototype,通过这个属性可以访问这个原型对象。

函数访问原型

//创建People构造函数
function People(){}
//访问People的原型对象(prototype属性)
console.log(People.prototype);

在这里插入图片描述
根据返回结果可以看出,People.prototype这个属性返回一个对象,这个对象中有一个属性constructor,该属性的值是People这个构造函数。

对象访问原型

所有对象都有__proto__属性,这个属性的值是创建这个对象的构造函数的原型对象。
这个属性是隐式原型.
与prototype不同的是,__proto__给浏览器识别的属性,它不是ECMAscript的语法规范,不推荐使用。
我们可以通过Object.getPrototype()这个方法访问对象的隐式原型对象

var obj = new Object();
console.log(Object.getPrototype(obj));

在这里插入图片描述

Object构造函数创建obj所以obj的隐式原型对象就是Object.prototype
我们可以看一下是否是Object.prototype

 console.log(Object.getPrototypeOf(obj) === Object.prototype);

在这里插入图片描述
由此可见,我们可以用Object.getPrototypeOf(obj)访问对象的原型对象

原型链

原型链是由多个原型相互联系形成的链式结构。
它与作用域链有些相似
我们可以创建一个简单的原型链

//创建一个构造函数
function People(){}
//实例化一个对象
var p1 = new People();

此时原型链就已形成
p1.proto --> People.prototype -->Object.prototype --> null
p1的隐式原型对象是People.prototype
People.prototype的隐式原型对象是Object.prototype
Object.prototype的隐式原型是null

原型链的作用

通过原型链可以访问原型上的属性和方法

该作用扩展了对象的可以访问的属性和方法的范围,同时也可以减少相同函数多次书写的情况,可以实现函数声明一次,在多个对象上调用的效果

//创建一个构造函数
function People(name){
	this.name = name;
}
//在People的原型上添加move方法
People.prototype.move = function(){
	console.log(this.name+'在移动');
}
//实例化一个对象
var p1 = new People('Mach');
p1.move();

在这里插入图片描述

通过上面的例子可以看到,p1本身没有move方法但是却能调用move方法就是因为原型链扩展了p1的访问范围,使得p1能够访问People.prototype上的方法
同时也说明了能够减少相同代码的书写,当实例化多个对象时,每个对象都可以通过原型链访问move方法,不必每个对象都重新创建一个move方法

继承

js中的继承与面向对象中的继承有些差异,其通过原型链实现继承
下面进行简单的继承

 function People(){}
 People.prototype.move = function(){
	console.log(this.name+'在移动');
}
function Man(name){
	this.name = name;
}
Man.prototype = People.prototype;
var p = new People();
var m = new Man('m');
m.move();

在这里插入图片描述
由此我们可以说m继承了People.prototype上的方法
但是这种方法有一些缺点,当在Man.prototype上进行更改时,People.prototype中的属性也会被更改
实例如下

Man.prototype.sleep =function(){
	this.name+'我在睡';
} 
console.log(People.prototype);

在这里插入图片描述
由此可见,People.prototype中有一个sleep方法,因此说明Man.prototype的更改对People.prototype产生了影响
那么怎样才能使Man.prototype不会影响People.prototype呢
我们可以借助第三个构造函数作为隔离
示例如下

 function People(){}
 People.prototype.move = function(){
	console.log(this.name+'在移动');
}
function Man(name){
	this.name = name;
}
function Fn(){}

Fn.prototype = People.prototype;
Man.prototype = new Fn();
var p = new People();
var m = new Man('m');
m.move();
Man.prototype.sleep =function(){
	this.name+'我在睡';
} 
console.log(People.prototype);

在这里插入图片描述
此时People.prototype中并没有sleep方法,因此将People.prototype与Man.prototype隔离开,使得两者不会相互影响。

总结

  1. prototype属性是每个函数都有的一个属性,该属性的值是一个对象
  2. proto 是每个对象都具有的属性,该对象指向其构造函数的prototype,但是该属性不是规范,不推荐直接使用,可以用Object.getPeototypeOf()方法代替
  3. 可以通过原型链实现继承,也可以扩展对象的可访问范围
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端御书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值