首页 > 编程知识 正文

js的原型和原型链(javascript原型和原型链)

时间:2023-05-06 07:08:17 阅读:82121 作者:4739

对于许多前端初学者来说,原型和原型链是非常头痛的问题,prototype、[[prototype]]是愚蠢而不清晰的。 今天,我们来分析一些原型和原型链。 如果这篇文章能让大家受益的话,那是我最大的成果。

原型对象

要知道几个属性:

创建的每个函数都有一个“原型”(prototype )属性,它是与当前对象的原型相对应的指针。 也就是说,prototype是通过调用构造函数创建的对象实例的原型对象。

所有原型对象都将自动分配“构造函数”属性。 该属性包含指向具有prototype属性的函数的指针。

调用构造函数创建新实例时,该实例内部将包含一个指向构造函数原型对象的指针“[[Prototype]]”。 此指针对应于Firefox、Safari和Chrome浏览器的__proto__属性。

看第一次可能会头晕,但没关系。 举个栗子来分析一下。

函数人员()

}

Person.prototype.name='可爱的灯泡;

Person.prototype.age=18;

person.prototype.say myself=函数{

控制台日志(myna meis ' this.name ),I am ' this.age ' years old!' );

(;

var人员1=新人员(;

var人员2=新人员(;

person1.name='平常的帅哥';

人员1.age=27;

人员1 .萨伊米塞尔夫(; //实例属性,我的名字一直以来的帅哥,I am 27 years old!

人员2 .萨伊米塞尔夫(; //原型属性,我的名字is张三,I am 18 years old!

删除人员1.name;

删除人员1.age;

人员1 .萨伊米塞尔夫(; //原型属性,我的名字is张三,I am 18 years old!

在上例中,您可以看到:

构造函数(Person )具有指向原型对象Person.prototype的prototype属性。

原型对象(Person.prototype )具有constructor属性,该属性指向具有原型对象的函数,即person.prototype.constructor=person

然后使用构造函数Person创建两个实例person1和person2。 每个实例都有一个名为person1. _ _ proto _ _=person2. _ _ proto _ _的属性,它是构造函数的原型对象

让我这样解释一下,大家心中应该对这三个属性形成了一定的概念。

使用原型对象的好处是,所有对象实例都可以共享其包含的属性和方法。

也就是说,上例中的person1和person2访问了相同的属性和相同的一组sayMyself ()函数。

将name和age属性添加到人员1时,人员1会优先访问自己的属性,阻止对原型中相应属性的访问,但原型属性不会更改。 可以使用delete删除人员1实例的属性,然后再次访问原型属性。 举个不恰当的例子,就像吃饭一样。 我们一定要先吃餐具。 碗里没饭了再吃锅里。 这是传说中想着锅里吃的吧。

原型链

构造函数、原型和实例的关系:每个构造函数(p )都有一个原型对象(P.prototype ),每个原型对象都有一个指向构造函数的指针实例) p )具有指向原型对象的内部指针。那么,如果将原型对象设置为与另一类型的实例相等,结果会怎么样呢? 很明显,此时的原型对象包含指向另一个原型的指针,而另一个原型也相应地包含指向另一个构造函数的指针。 如果另一个原型又是另一个类型的实例,则上述关系依然成立,并以这种方式分层推进,构成了实例和原型链。 这是原型链的基本概念。

概念无聊无聊。 请给我同样的栗子。

函数人员()

}

Person.prototype.name='可爱的灯泡;

Person.prototype.age=18;

/p>

Person.prototype.sayMyself = function () {

console.log('my name is ' + this.name + ', I am ' + this.age + ' years old!');

};

function MoreMsg() {

}

MoreMsg.prototype.job = 'teacher';

MoreMsg.prototype = new Person();

var person = new MoreMsg();

person.sayMyself(); // my name is 张三, I am 18 years old!

console.log(person.job); // undefined

MoreMsg.prototype.job = 'programmer';

MoreMsg.prototype.constructor = MoreMsg; // 如需要,使得constructor重新指向MoreMsg

console.log(person.job); // programmer

以上例子定义了两个构造函数Person和MoreMsg,两个构造函数有着各自的属性和方法,MoreMsg继承了Person,而继承是通过重写原型对象MoreMsg.prototype,取而代之是Person的实例。结合前一个例子,我们可以这样理解,本例中的MoreMsg.prototype就相当于是前一个例子中的person1或person2,因为person1包含一个指向对应原型对象的内部指针(person1.__proto__ = Person.prototype),所以可以推断出此时的原型对象MoreMsg.prototype包含一个指向另一个原型对象Person.prototype的指针,即MoreMsg.prototype.__proto__ = Person.prototype,这样就构成了一个实例与原型的链条。

本例中,重写了原型对象MoreMsg.prototype,因此重写之前给MoreMsg.prototype添加的属性全部作废,所以第一次console.log(person.job)才会输出undefined,而且MoreMsg.prototype.constructor属性也就变成了新对象的constructor属性(指向Person构造函数),不再指向MoreMsg函数,如需使得constructor重新指向MoreMsg,则需要执行MoreMsg.prototype.constructor = MoreMsg。

就好比我们玩游戏,一个号玩了很久,突然想重新玩一个号,那前一个号就白玩了,必须重头开始玩。

所有函数的默认原型都是Object的实例,因此默认原型都会包含一个内部指针,指向 Object.prototype。

所以,上述例子展示的原型链中还包括另外一个继承层次(Object)。

原型和原型链就介绍到这,如果大家第一遍没看懂,没关系,再看几遍,跟着多敲几遍代码;如果依然不懂,还是没关系,工作一段时间后,等js比较熟练后,回过头来再看看,你会发现你突然就顿悟了。

------------笑对人生,能穿透迷雾;笑对人生,能坚持到底;笑对人生,能化解危机;笑对人生,能照亮黑暗。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。