js每个对象拥有一个原型对象吗?


任何一个JavaScript对象(一般有对花括号)都有一个原型对象,这个原型对象是JavaScript语言内置的,JavaScript对象可以使用原型对象的属性和方法。

也可以这样理解:每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性。

再来一通不怎么好理解的:

Function产生的对象是函数对象,其他对象都是普通对象。两个基本:①只要创建了对象(无论是函数对象还是普通对象),都自带一个_proto_属性(可称为隐式原型),一个对象的隐式原型指向构造该对象的构造函数的原型,这也保证了实例能够访问在构造函数原型中定义的属性和方法。②其中函数对象除了和其他对象一样有上述_proto_属性之外,还有自己特有的属性——原型属性(prototype),这个属性是一个指针,指向的对象正是调用该构造函数而创建的实例的原型,这个对象的用途就是包含所有实例共享的属性和方法(我们把这个对象叫做原型对象)。原型对象也有一个属性,叫做constructor,这个属性包含了一个指针,指回原构造函数。

每个javascript对象都有一个原型对象,这个对象在不同的解释器下的实现不同。比如在firefox下,每个对象都有一个隐藏的__proto__属性,这个属性就是“原型对象”的引用。如果对象没有显式的声明自己的”__proto__”属性,这个值默认的设置为Object.prototype,而Object.prototype的”__proto__”属性的值为”null”,标志着原型链的终结。

由于原型对象本身也是对象,根据上边的定义,它也有自己的原型,而它自己的原型对象又可以有自己的原型,这样就组成了一条链,这个就是原型链,JavaScritp引擎在访问对象的属性时,如果在对象本身中没有找到,则会去原型链中查找,如果找到,直接返回值,如果整个链都遍历且没有找到属性,则返回undefined.原型链一般实现为一个链表,这样就可以按照一定的顺序来查找。

//每一个对象都有它的原型对象,它可以使用自己原型对象上的所有属性和方法 //2、通过构造函数的prototype属性拿到原型

下面来简单说说原型在实际项目中有什么用?

 注意一点:扩展对象

举一个例子:我希望自己实现一个功能,输出特定格式的日期字符串

//原型对象有什么作用

在ES5时我们是使用构造函数来创建对象,到了ES6时加入了新语法来帮助我们创建对象,在类中加入属性方法

由于这个新特性,我们获取原型的方法又多了一条

继承:子对象可以使用父对象上的所有属性和方法

(一)ES6中类的继承

我们来通过一个场景来帮组理解

博客用户和管理员,两者都可以登录博客,但管理员可以删除一个人 //博客用户和管理员,两者都可以登录博客,但管理员可以删除一个人

 (二)ES5中的继承(基于原型的继承)

Admin对象可以使用原型上的所有属性和方法(特性)。若将原型对象设置为User的实例,那么Admin就可以使用User的所有的属性和方法。这就是一个基于原型的继承。像一个链条串起来了。

//博客用户和管理员,两者都可以登录博客,但管理员可以删除一个人

这种原型对象链式的继承和调用我们称之为原型链。

类中的extend可理解为相当于下面的
 

 下面有个有趣的例子

 
 
1、首先,在Oject原型上设置一个login方法

2、然后,声明和初始化一个数组

 object原型是底层的对象,任何一个对象(引用类型)都可以使用在object上创建的方法。

2)对象和prototype对象是继承关系吗?

3)__proto__ 和 prototype区别,在普通对象、函数对象中表现为啥样的?

  每个javascript对象都有一个原型对象,这个对象在不同的解释器下的实现不同。比如在firefox下,

每个对象都有一个隐藏的__proto__属性,这个属性就是“原型对象”的引用。

  由于原型对象本身也是对象,根据上边的定义,它也有自己的原型,而它自己的原型对象又可以有自

己的原型,这样就组成了一条链,这个就是原型链,JavaScritp引擎在访问对象的属性时,如果在对象本

身中没有找到,则会去原型链中查找,如果找到,直接返回值,如果整个链都遍历且没有找到属性,则返

回undefined.原型链一般实现为一个链表,这样就可以按照一定的顺序来查找。

我们先用一个构造器来实现一个构造函数:

//下面则说明构造函数实例化后,分配着不同的实例对象,互不相关 //下面则说明了new操作符的一项作用,即将原型中的this指向当前对象, //但是实例对象this中没有mark2值,则在原型链向上寻找,得到A原型对象中的mark2值, //在赋值时,将修改后的值添加在了a实例中。 //总:虽然调用的是prototype方法,但是不会对prototype属性做修改,只会说是在实例中新增属性,但是在使用时,会最使用最近得到的属性(在后面原型链中可以加以理解)

为什么a可以使原型中的changeMark2方法?这就和js巧妙的原型链相关,在Firefox中我们可以打印出对象并可查看到对象下面的__proto__。

我们把上面的过程用流程图来表示:

只有构造函数才会有prototype属性,而实例化出来的对象会拥有__proto__,而不会有prototype。

像上图画的那样,两个实例化的对象都通过__proto__属性指向了A.prototype(即构造函数的原型对象)

so:当使用对象的方法或属性时,对象会在一步一步通过__proto__向上寻找,找到最近的则是最终的获取到的方法或属性。

  ————这就是js中的原型链。

 就像图上看到的一样,所有对象的原型链最终都指向了Object对象,而Object的原型对象(Object.prototype)是为数不多的不继承自任何属性的对象,即Object.prototype没有__proto__,是原型链的顶峰。

通过上面我们可以了解到,当我们对A.prototype或Object.prototype添加属性或方法时,在a和a2实例中都会查看到该属性或方法,因为这两个实例都通过原型链与A和Object的原型对象相连。

 再来看看原型对象和原型链在继承方面的实现:

再构造一个函数A和一个函数B,并让B继承A,如下:

//上面语句和下语句作用相同

其中的结构示意大概如下图:

用《JavaScript权威指南》中的对于constructor的解释为:对象通常继承的constructor均指代它们的构造函数,而构造函数是类的“公共标识”。即constructor可用来判断对象所属的类。

在上面的小例子中,用instanceof也可判断对象的类,但是有自身的缺陷,instanceof的实现方法为:

instanceof不会去检查temp是不是由TEMP()构造函数初始化的,面是判断temp是否继承自TEMP.prototype,这样,范围就宽了很多。

如在上面的大例中,使用

  可以说instanceof是用来检测继承关系的。而当

  但我们知道的b是属于B类的,那最后所以要做的就是:

dog是函数对象,本身没有price属性,此时dog的__proto__属性指向的是其构造函数的原型。

我要回帖

更多关于 原型对象和对象原型的区别 的文章

 

随机推荐