我是靠谱客的博主 虚拟豌豆,最近开发中收集的这篇文章主要介绍JS中__proto__和prototype都是什么?原型链继承解读,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

首先要知道,prototype是函数才有的属性,__proto__是每个对象都有的属性

随后,先谈一下

1.什么是prototype?

prototype对象是JS实现面向对象的一个重要机制。

在很早以前,js中是没有class这个概念的(现在js中的class是函数的语法糖)
每个函数就是一个对象(Function类型),函数对象都有一个子对象 prototype对象,在创建这个函数对象的时候,prototype会自动成为这个对象的成员。

prototype表示该函数的原型,也表示一个类的成员的集合,简称“原型”。
在这里插入图片描述

JS的设计者最初参考了c等的设计,引入了new关键词,用来从原型创建对象

比如

function people(name){
this.name=name
}
 
var a=new people("小明");
var b=new people("法外狂徒张三");
 
alert(a.name)//小明

为了解决每个示例的信息不共享的弊端,JS设计者引入了prototype属性

prototype 属性包含一个prototype对象(这在第一个图中也有显示)

所有实例对象需要共享的属性和方法,都放在这个对象里面

那些不需要共享的属性和方法,就放在构造函数里面


function people(name){
this.name=name
}
 
people.prototype = { sex : '男性' };
var a=new people("小明");
var b=new people("法外狂徒张三");
alert(a.sex);
alert(b.sex);
//都是“男性”

对于people这个函数(也就是构造器),所有基于他的实例都使用同一个prototype

通过prototype,可以实现js中对象的继承(当然js引入class后,也可以用extends实现了)

function A(){
}
A.prototype.show=function(){//扩充函数A的方法show
   alert('A');
}
 
function B(){
   alert('B');
 }

 B.prototype = new A();
 //让B的prototype继承A的,这时B也有了show方法
执行一下A.prototype.show()和B.prototype.show()

弹出内容都是A

那么,是时候谈谈__proto__了

2.__proto__又是什么?

首先,__proto__是每个对象都有的隐性属性,这个属性指向刚刚讲的prototype

在这里插入图片描述

在这里创建了一个没有内容的对象,但对象里面有一个[[Prototype]],这个prototype实际上是window.Object.prototype

这里说一下,在你的JS还没开始运行,浏览器就有一个叫做window的对象

在这个对象里,有很多大家很熟悉的东西
在这里插入图片描述

(下面还有很多,不截了)

比如我们常用的document,也是window的一个属性

而用于取DOM的getElementById()这些就是document里面的函数

不过平时使用的时候,省略了window
在这里插入图片描述
(完整地是这样)

那么,因为window 对象有一个 Object 属性,而window.Object 是一个函数对象
所以,window.Object也有prototype
所有对象会像上面写prototype那样继承window.Object的prototype
window.Object.prototype 里有 toString这个函数方法,一会用它举例子

这里引用知乎上的例子

回到刚刚的代码

let obj={}
obj.toString()

首先,我们创建的这个对象没有内容,那他为什么有toString方法?(当然还有别的很多方法)

那是因为上面也讲到的,obj里有默认一个空对象__proto__指向prototype,这个prototype实际上是window.Object.prototype

这就联系起来了

调用 obj.toString 的时候,实际上调用 window.Object.prototype.toString

那么 window.Object.prototype.toString 是怎么获取 obj 的内容的呢?

那是因为 obj.toString() 等价于 obj.toString.call(obj)

同时 obj.toString.call(obj) 等价于 window.Object.prototype.toString.call(obj)

那么同理,如果有一个数组

var a=[];
a.push(1);
是怎么执行的?

首先,a是一个空的数组对象,本身也没有push方法,而数组对象和上面类似的,继承window.Array函数对象

所以毫无疑问,a.__proto__指向window.Array的prototype

所以a没有push,就向window.Array要push方法

也就是说,

arr.push 实际上调用了 window.Array.prototype.push

那么 window.Array.prototype.push 是怎么获取 a 的呢?

arr.push(1) 等价与 arr.push.call(arr,1)

arr.push.call(arr,1) 等价于 window.Array.prototype.push.call(arr, 1)

那么再联系起来,如果是

let a=[];
a.push(i=1);
a.toString();

第三句,a.toString是怎么执行的(window.Array.prototype也没有toString方法,地主家也没有余粮啊)

不要忘了上面写的,所有对象继承window.Object的prototype

你window.Array.prototype没有,你的老大window.Object.prototype有啊

所以a.__proto__没有,就去找a.proto.proto

所以 a.toString() 其实就是 window.Object.prototype.toString()

a.toString() 等价于 arr.toString.call(a)

arr.toString.call(a) 等价于 window.Object.prototype.toString.call(a)

综上,prototype是JS实现继承的方法,用于实现示例继承属性和方法

而__proto__是一个所有对象都有的空对象,指向上一级的prototype

从而实现了属性和方法的继承

这也就是JS中原型链方式的继承

(第一次写这种文,如有披露请见谅和指正)

参考:

https://www.zhihu.com/question/56770432/answer/315342130

http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javascript.html

最后

以上就是虚拟豌豆为你收集整理的JS中__proto__和prototype都是什么?原型链继承解读的全部内容,希望文章能够帮你解决JS中__proto__和prototype都是什么?原型链继承解读所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(35)

评论列表共有 0 条评论

立即
投稿
返回
顶部