原型
网上看了不少有关原型的讲解,但是感觉很绕,理解起来云里雾里。好像是理解了,又好像没彻底理解。过了几天又全部忘记了。那今天我就来说说原型,让大家彻底搞懂原型的知识。
关于原型讲解混乱的原因:
- 对原型的称呼没有统一,有叫原型对象,对象原型的,有叫显示原型,隐式原型的。那么这里为了称呼方便,我这里只将__proto__这个非标准属性称为原型。至于prototype,我就直接叫prototype属性。
- 网上有些是从对象开始讲解原型的。没有从更上层的Object来讲解原型。所以就是感觉弄懂了但是又没彻底弄懂,或者说弄懂了,过不久又会忘记了。就是因为没有理解原型的逻辑。所以我先从Object去探讨原型。
Object
大家有没有思考过Object是什么
打印一下看看
console.log(typeof Object)
Object是一个函数。
那么我们来看看这个顶级函数里有什么
console.dir(Object)
javascript内置的Object函数中包含的内容大致分为三类:
- 静态方法 即这些方法只能通过Object来调用比如:Object.keys()
- prototype属性
- Object的原型(在浏览器中是以[[Prototype]]的形式存在,用户可以使用__proto__来调用)
我们来思考一下,这三类的作用到底是什么。
静态方法
顾名思义,这些方法只能通过Object来调用。比如:Object.keys()等。Object中提供的大部分方法都是静态方法。
prototype属性
Object既然是一个函数,那么它就可以用new关键字来创建对象。
当然我们定义一个对象一般是用字面量的形式,比如 let foo={}。但是js引擎的底层为我们编译对象字面量的时候会重新new一个对象,然后将字面量的属性与方法放入这个新对象中
Object想要把一些只有对象能使用的方法交给对象,那么Object所创建的对象都能使用这些方法。
这些方法就是放在Object.prototype中,那么怎么交给对象呢?
交给对象的__proto__。所以有说法__proto__叫做对象原型就是这个道理,那么在这里我就称呼__proto__叫做原型
所以产生了一个公式:
Object.prototype=对象.__proto__
我们来看一下它的内容
可以看出,Object仅仅把6个方法交给了对象,而且有三种方法hasOwnProperty,isPrototypeOf,propertyIsEnumerable是返回boolean值的。方法少,而且功能较单一。
总而言之,Object.prototype就是把一些方法交给对象使用的
Object的原型
为什么Object上也有__proto__?
刚刚说过对象有个__proto__,用来获取一些方法。莫非Object也是一个对象吗?
没错,Object也是一个对象,创造它的父级就是Function。Function.prototype把一些函数会使用的方法交给了函数的__proto__。
我们来看一下,Object的__proto__里有什么内容
所以函数为什么能用bind,call,apply等方法了。本质上就是把函数当作对象了,然后调用了bind,call,apply方法而已
Function的上级又是谁呢
console.dir(Function);
如图可以得到:
console.log(Function.__proto__ === Function.prototype);
Function的上级竟然是它自己!!!
总结
以上就是本小结的内容,我来总结一下。 javascript中有个函数Object,它既可以当作函数,也可以当作对象。Object中包含三类东西。
-
静态方法:即这些方法只能通过Object来调用比如:Object.keys(),Object.values()等。而且Object提供的大部分都是静态方法。
-
prototype属性:当Object作为函数时候,Object把交给对象使用的方法放入了prototype中将其赋值给了对象的__proto__。其形式用代码表示为:
Object.prototype=对象.__proto__
-
Object的原型(在浏览器中是以[[Prototype]]的形式存在,用户可以使用__proto__来调用): 当Object作为对象时候,它接受了Function.prototype中的方法。所以函数也能使用call,apply等方法。
其实,在Javascript中引用类型有函数与对象。Javascript想把一些方法交给函数来使用,想把一些方法交给对象来使用。
怎么给,怎么拿?
函数来给,对象来拿
函数怎么给,对象怎么拿?
函数用prototype属性来给,对象用__proto__来拿。最后函数又可以作为对象从Function.prototype中获取方法
所以原型就是解决以上问题才出现的。用专业点的话说,原型就是用来实现继承。
下一节
现在我们知道了Object与原型的关系,那么常说的原型链又是怎么一回事呢?下一节就来说说原型链的故事。
创作不易,如果觉得还行,点点赞吧!