We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
首先我们需要明确两点:
1️⃣__proto__和constructor是对象独有的
__proto__
constructor
2️⃣prototype属性是函数独有的
prototype
因此,prototype 描述的是两个对象之间的某种关系(其中一个,为另一个提供属性访问权限)。
下面通过一个例子来说明:
function Demo() {} console.log(Demo.prototype.constructor === Demo) // true console.dir(Demo.prototype)
![](C:\Users\DayDay\Pictures\Camera Roll\demo.png)
可以看到就是Demo函数对象的prototype原型是右边这个对象,那么Demo.prototype原型上有个constructor属性,这个属性正好指向Demo函数本身。
所有你可以理解成:
A的显示原型是B,则有: A.prototype === B B.constructor === A
我觉得这样子唯一的好处在于你可以找到我,我也可以找到你。好滑稽
再次强调 :
1️⃣__proto__和constructor是对象独有的。2️⃣prototype属性是函数独有的
关于更多__proto__更深入的介绍,可以参看工业聚大佬的《深入理解 JavaScript 原型》一文。
怎么理解呢?我们通过内存结构图来看看吧
function Demo() {} Demo.prototype.say = () => { //给原型添加say方法 console.log("hello world") } console.log(Demo.prototype.say) let fn = new Demo(); fn.say(); // 怎么找到say方法的呢? console.log(fn.__proto__ === Demo.prototype) // true
我们从图中可以看到,Demo函数的原型跟它构造函数(Demo)创建的实例fn.__proto__指向同一个对象。
那么fn是怎么找到say方法的呢?
更加具体的说就是通过隐式原型__proro__找到的,分析如下:
__proro__
那么是不是可以更加准确的说明:实例是通过隐式原型__proto__查找需要调用的属性的,那么我们通过接下来的代码去验证一下。
隐式原型__proto__
代码:
function Demo() {} Demo.prototype.say = () => { //给原型添加say方法 console.log("hello world") } Demo.prototype.name = 'old name' let fn = new Demo(); fn.say(); // 怎么找到say方法的呢? console.log(fn.name) console.log("为修改前",fn.__proto__ === Demo.prototype) // true console.log("-------接下来修改fn的__proto__") fn.__proto__ = { say: () => { console.log("hello 隐式原型") }, name : 'new name' } console.log("修改实例中的隐式原型",fn.__proto__ === Demo.prototype) // true console.log(fn.name) fn.say() console.log("重新创建一个Demo构造函数实例") let demo1 = new Demo(); console.log(Demo.prototype === demo1.__proto__) demo1.say()
首先的说明的是:
通过查阅相关的文档,ES6之前不能直接操作隐式原型,也不推荐你这么做。
通过修改fn的隐式原型,让它指向一个新的对象。那么fn.proto 不等于Demo.prototype. 这个例子也能证明一点,实例对象调用属性时,实例对象不具有该属性时,是通过隐式原型去找的该属性的,找不到的话,在它的隐式原型对象的隐式原型对象上找。
这也就是我们常说的,在原型上添加属性或者方法,实例可以共享,原因就在于我们并不推荐去修改实例的__proto__属性,这样子也就是会有一下结果:
function Demo() { // 内部语句 this.prototype = {} } let fn = new Demo(); // 内部语句: fn.`__proto__` = Demo.prototype // 实例化一个对象隐式原型会默认赋值: fn.__proto__ = Demo.prototype // 定义函数时: 显式原型也会默认添加: Demo.prototype = new Object()
这里我们需要知道的是,__proto__是对象所独有的,并且__proto__是一个对象指向另一个对象,也就是他的原型对象。我们也可以理解为父类对象。它的作用就是当你在访问一个对象属性的时候,如果该对象内部不存在这个属性,那么就回去它的__proto__属性所指向的对象(父类对象)上查找,如果父类对象依旧不存在这个属性,那么就回去其父类的__proto__属性所指向的父类的父类上去查找。以此类推,知道找到 null。而这个查找的过程,也就构成了我们常说的原型链。
null
Object
Function
**最后总结: ** 先有Object.prototype(原型链顶端),Function.prototype继承Object.prototype而产生,最后,Function和Object和其它构造函数继承Function.prototype而产生。
使用__proto__是有争议的,也不鼓励使用它。因为它从来没有被包括在ECMAScript语言规范中,但是现代浏览器都实现了它。__proto__属性已在ECMAScript 6语言规范中标准化,用于确保Web浏览器的兼容性,因此它未来将被支持。它已被不推荐使用, 现在更推荐使用Object.getPrototypeOf/Reflect.getPrototypeOf 和Object.setPrototypeOf/Reflect.setPrototypeOf(尽管如此,设置对象的[[Prototype]]是一个缓慢的操作,如果性能是一个问题,应该避免)。
Object.getPrototypeOf
Reflect.getPrototypeOf
Object.setPrototypeOf
Reflect.setPrototypeOf
proto 属性也可以在对象文字定义中使用对象[[Prototype]]来创建,作为Object.create() 的一个替代。
Object.create()
a prototype may have a non-null implicit reference to its prototype, and so on; this is called the prototype chain.
如上,在 ECMAScript 2019 规范里,只通过短短的一句话,就介绍完了 prototype chain
原型链的概念,仅仅是在原型这个概念基础上所作的直接推论。
既然 prototype 只是恰好作为另一个对象的隐式引用的普通对象。那么,它也是对象,也符合一个对象的基本特征。
每个对象都可以有一个原型_proto_,这个原型还可以有它自己的原型,以此类推,形成一个原型链。查找特定属性的时候,我们先去这个对象里去找,如果没有的话就去它的原型对象里面去,如果还是没有的话再去向原型对象的原型对象里去寻找...... 这个操作被委托在整个原型链上,这个就是我们说的原型链了。
深入理解 JavaScript 原型
一文吃透所有JS原型相关知识点
JavaScript深入之从原型到原型链
从__proto__和prototype来深入理解JS对象和原型链
js原型链
The text was updated successfully, but these errors were encountered:
daydaylee1227
No branches or pull requests
前言
写在前面
首先我们需要明确两点:
1️⃣
__proto__
和constructor
是对象独有的2️⃣
prototype
属性是函数独有的原型
prototype
因此,prototype 描述的是两个对象之间的某种关系(其中一个,为另一个提供属性访问权限)。
constructor与prototype联系
下面通过一个例子来说明:
![](C:\Users\DayDay\Pictures\Camera Roll\demo.png)
可以看到就是Demo函数对象的prototype原型是右边这个对象,那么Demo.prototype原型上有个constructor属性,这个属性正好指向Demo函数本身。
所有你可以理解成:
我觉得这样子唯一的好处在于你可以找到我,我也可以找到你。好滑稽
__proto__
和prototype关系再次强调 :
1️⃣
__proto__
和constructor
是对象独有的。2️⃣prototype
属性是函数独有的关于更多
__proto__
更深入的介绍,可以参看工业聚大佬的《深入理解 JavaScript 原型》一文。显示原型和隐式原型
__proto__
, 及隐式原型(属性)**怎么理解呢?我们通过内存结构图来看看吧
我们从图中可以看到,Demo函数的原型跟它构造函数(Demo)创建的实例fn.
__proto__
指向同一个对象。那么fn是怎么找到say方法的呢?
更加具体的说就是通过隐式原型
__proro__
找到的,分析如下:__proro__
属性对应的原型那么是不是可以更加准确的说明:实例是通过
隐式原型__proto__
查找需要调用的属性的,那么我们通过接下来的代码去验证一下。代码:
首先的说明的是:
通过查阅相关的文档,ES6之前不能直接操作隐式原型,也不推荐你这么做。
通过修改fn的隐式原型,让它指向一个新的对象。那么fn.proto 不等于Demo.prototype. 这个例子也能证明一点,实例对象调用属性时,实例对象不具有该属性时,是通过隐式原型去找的该属性的,找不到的话,在它的隐式原型对象的隐式原型对象上找。
这也就是我们常说的,在原型上添加属性或者方法,实例可以共享,原因就在于我们并不推荐去修改实例的
__proto__
属性,这样子也就是会有一下结果:这里我们需要知道的是,
__proto__
是对象所独有的,并且__proto__
是一个对象指向另一个对象,也就是他的原型对象。我们也可以理解为父类对象。它的作用就是当你在访问一个对象属性的时候,如果该对象内部不存在这个属性,那么就回去它的__proto__
属性所指向的对象(父类对象)上查找,如果父类对象依旧不存在这个属性,那么就回去其父类的__proto__
属性所指向的父类的父类上去查找。以此类推,知道找到null
。而这个查找的过程,也就构成了我们常说的原型链。总结
__proto__
属性:创建一个对象实例时,默认值是构造函数的prototype属性值,也就是上面所说的补充
Object
和Function
的鸡和蛋的问题**最后总结: ** 先有Object.prototype(原型链顶端),Function.prototype继承Object.prototype而产生,最后,Function和Object和其它构造函数继承Function.prototype而产生。
MDN的推荐
使用
__proto__
是有争议的,也不鼓励使用它。因为它从来没有被包括在ECMAScript语言规范中,但是现代浏览器都实现了它。__proto__
属性已在ECMAScript 6语言规范中标准化,用于确保Web浏览器的兼容性,因此它未来将被支持。它已被不推荐使用, 现在更推荐使用Object.getPrototypeOf
/Reflect.getPrototypeOf
和Object.setPrototypeOf
/Reflect.setPrototypeOf
(尽管如此,设置对象的[[Prototype]]是一个缓慢的操作,如果性能是一个问题,应该避免)。proto 属性也可以在对象文字定义中使用对象[[Prototype]]来创建,作为
Object.create()
的一个替代。prototype chain 原型链
如上,在 ECMAScript 2019 规范里,只通过短短的一句话,就介绍完了 prototype chain
原型链的概念,仅仅是在原型这个概念基础上所作的直接推论。
既然 prototype 只是恰好作为另一个对象的隐式引用的普通对象。那么,它也是对象,也符合一个对象的基本特征。
结论:
__proto__
是原型链查询中实际用到的,它总是指向 prototype参考
深入理解 JavaScript 原型
一文吃透所有JS原型相关知识点
JavaScript深入之从原型到原型链
从__proto__和prototype来深入理解JS对象和原型链
js原型链
The text was updated successfully, but these errors were encountered: