关于原型你需要知道的几个问题
标签:
JavaScript
为了良好的代码高亮阅读体验,建议您查看github原文。
前言
prototype是js面向对象的一个重要机制,于是总结了以下几个问题,理解起来会比较有针对性。
1. prototype
和 __proto__
的关系是什么?
prototype
是只有函数才会有的属性;而__proto__
是所有对象都有的属性。
几乎所有的函数都有一个prototype
属性,prototype
上挂载的所有属性和方法都可以被这个函数的实例继承。
对于
function Foo(){}const foo=new Foo()// 注意这里:无论在实例化前后在prototype上添加属性实例都会继承Foo.prototype.isTestable=trueconsole.log(foo.isTestable) // true
有
Foo.prototype===foo.__proto__ //truefoo.constructor===Foo // trueFoo.constructor===Function // trueFoo===foo.__proto__.constructor // true
是不是看起来很乱?祭上我多年收藏的此图!!OVO
demo
2. 自有属性和原型属性又是什么?
上面的例子中,在调用foo.isTestable
时,先会在实例上查询是否有isTestable
这个属性;如果没有找到,再往它的__proto__
上查询这个属性;直至查到底层没有则返回undefined
。
function Foo(){}const foo=new Foo() Foo.prototype.isTestable=trueconsole.log(foo.isTestable) // true
那么如何区分某个对象的属性时其自身的还是继承的呢?我们就需要hasOwnProperty()
这个方法来确认。
其中isTestable
这个属性对于foo
来说就是原型上的属性,所以它返回false
foo.hasOwnProperty('isTestable') // false
如果我们在foo
上直接添加isTestable
这个属性,那么他与__proto__
上的isTestable
是否冲突?
function Foo(){}const foo=new Foo() foo.isTestable=falseFoo.prototype.isTestable=trueconsole.log(foo.hasOwnProperty('isTestable')) // trueconsole.log(foo.isTestable) // falseconsole.log(foo.__proto__.isTestable) // true// 删除实例上的isTestable属性delete foo.isTestableconsole.log(foo.hasOwnProperty('isTestable')) // falseconsole.log(foo.isTestable) // true 这时又从__proto__上找到isTestable了// 来,我们把__proto__上面的也删掉delete foo.__proto__.isTestableconsole.log(foo.isTestable) // false, isTestable终于没了
当然hasOwnProperty()
只能知道某个属性是否在实例上,如果我们想要知道某个属性是否在__proto__
上,就需要自己写一个函数:
const hasPrototypeProperty=(obj,key)=>(key in obj)&&(!obj.hasOwnProperty(key))
3. 每个实例之间的关系是什么?
对于以下由一个构造函数创建的实例
function Foo(){}const foo1=new Foo()const foo2=new Foo()
有下列关系
foo1==foo2 // false,这是因为在这里都指向不同的内存,{}==={} // falseJSON.stringify(foo1)===JSON.stringify(foo2) // truefoo1.constructor===foo2.constructor // true 这里的构造函数都指向Foo,所以为truefoo1.__proto__===foo2.__proto__ // 当然这个也为truefoo1.__proto__===Foo.prototype // trueObject.getPrototypeOf(foo1)===Object.getPrototypeOf(foo2) // true
4. 在构造函数中添加属性后实例怎么继承
对于在构造函数内部添加的属性,它的实例会继承它的属性;
function Foo(){this.name='foo'} Foo.age=10const foo1=new Foo()
然而直接挂载在Foo上的属性不会在实例上被继承;
foo1.name // 'foo'foo1.age // undefined
如果实例上和原型上都挂载了同样的属性,会优先从实例上获取:
function Foo(){this.name='foo'}const foo1=new Foo() foo1.name='ahaha'foo1.name //'ahaha'
参考文档
作者:mytac
链接:https://www.jianshu.com/p/bb02c403f86c
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦