手机版

谈JS原型对象和原型链

时间:2021-09-17 来源:互联网 编辑:宝哥软件园 浏览:

在Javascript中,一切都是一个Object,但是对象之间是有区别的,大致可以分为两类:普通对象和Function对象。

一般来说,新Function生成的对象是函数对象,其他对象是普通对象。

举个例子:

函数f1(){ //todo}var f2=函数(){//todo };var f3=新函数(' x ',' console . log(x)');var O1={ };var o2=新对象();var o3=新f1();console.log(typeof f1,//function typeof f2,//function typeof f3,//function typeof o1,//object typeof o2,//object type of O3//object);function function object是函数的声明,定义函数最常见的方式是f2实际上是一个匿名函数,赋给f2,属于函数表达式。f3不常见,但也是一个函数对象。

是函数JS的对象。当创建f1和F2时,JS将通过新的Function()自动构建这些对象。因此,这三个对象是由新的Function()创建的。

在Javascript中创建对象有两种方式:文字对象和新表达式。o1和o2的产生正好对应这两种方式。关注o3。如果用Java和C#理解,o3是f1的实例对象,o3和f1是同一类型。至少我之前是这么想的,但事实并非如此…

那么如何理解呢?很简单,看o3是不是新Function生成的,显然不是。既然不是函数对象,那就是普通对象。

在简单了解了函数对象和普通对象之后,让我们来看看Javascript中的原型和原型链:

在JS中,每当创建一个函数对象f1时,都会在对象中构建一些属性,包括prototype和_ _ prototype _ _。Prototype是一个原型对象,它记录了f1的一些属性和方法。

请注意,prototype对f1是不可见的,也就是说,f1不会在prototype中寻找属性和方法。

函数f(){ } f . prototype . foo=' ABC ';console . log(f . foo);//undefined那么,原型有什么用呢?其实原型的主要功能是继承。一般来说,prototype中定义的属性和方法都是为自己的“后代”保留的,所以子类完全可以访问prototype中的属性和方法。

要知道f1是如何把原型留给“后代”的,我们需要知道JS中的原型链。这个时候JS中的_ _ prototype _ _进入了,很奇怪,很隐蔽,你经常看不到,但是它既存在于普通对象中,也存在于函数对象中,它的作用是保存父类的原型对象。JS通过新表达式创建对象时,通常会将父类的原型赋给新对象的__proto__属性,从而形成代与代的继承…

函数f(){ } f . prototype . foo=' ABC ';var obj=new f();console . log(obj . foo);//abc现在我们知道obj中的__proto__存储了F的原型,那么F的原型中的__proto__存储了什么呢?请看下图:

如图所示,Object.prototype存储在f.prototype的_ _ prototype _ _中,object.prototype中也存在_ _ prototype _ _从输出结果来看,object.prototype. _ _ prototype _ _为空,表示obj对象的原型链结束。如下图所示:

obj对象有了这样的原型链之后,在执行obj.foo的时候,obj会先找出它是否有这个属性,但是不会找到它的原型。当foo没有找到时,obj将依次沿着原型链搜索…

在上面的例子中,我们在f的原型上定义了foo属性,然后obj会在原型链上找到这个属性并执行它。

最后,用几句话概括本文涉及的要点:

原型链的形成真的是靠_ _ prototype _ _而不是原型。JS引擎在执行一个对象的方法时,首先会发现该方法是否存在于对象本身中。如果不存在,它会查找原型链,但不会查找自己的原型。对象的__proto__记录它自己的原型链,并确定它自己的数据类型。更改__proto__相当于更改对象的数据类型。函数的原型不属于它自己的原型链。它是创建子类的核心,决定子类的数据类型,是连接子类原型链的桥梁。在原型对象上定义方法和属性的目的是被子类继承和使用。以上就是本文的全部内容,希望对大家的学习有所帮助。

版权声明:谈JS原型对象和原型链是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。