共计 2741 个字符,预计需要花费 7 分钟才能阅读完成。
[TOC]
到底什么是 JS 原型
转载自 blog:到底什么是 JS 原型
话说在前头,去网上查问很多对于 JS 原型的解释的文章,其中有 80% 看了都会不知所云,大多数对于 JS 原型的解释的文章或者视频,都疏忽了很多读者对一些专业名词、概念是不把握的,或者你说的一句话,就能够绕晕读者,导致大家走了很多很多弯路。在这里先分享我查到的一篇对于 JS 原型的解释,是最通俗易懂的,地址。
一、首先大家在对 JS 原型进行解释的时候,会波及两个概念:构造函数、原型对象
1. 构造函数:艰深的一句话说,就是你在 script 标签外面申明的那个函数:
<body>
<script>
function students() {/* 我就是构造函数 */}
</script>
</body>
2. 原型对象:在申明了一个函数之后,浏览器会主动依照肯定的规定创立一个对象,这个对象就叫做原型对象。这个原型对象其实是贮存在了内存当中。
3. 在申明了一个函数后,这个构造函数(申明了的函数)中会有一个属性 prototype,这个属性指向的就是这个构造函数(申明了的函数)对应的原型对象;原型对象中有一个属性 constructor,这个属性指向的是这个构造函数(申明了的函数)。上面一张图能够很简略了解:
二、应用构造函数创建对象
咱们的构造函数应用 new 来创建对象的时候,就像上面这样:
<body>
<script>
function students() {/* 我就是构造函数 */}
var stu = new students();
</script>
</body>
此时,stu 就是那个构造函数 students 创立进去的对象,这个 stu 对象中是没有 prototype 属性的,prototype 属性只有在构造函数 students 中有,请看图!
能够看出,构造函数 students 中有 prototype 属性,指向的是 students 对应的原型对象;
而 stu 是构造函数 students 创立进去的对象,他不存在 prototype 属性,所以在调用 prototype 的时候的构造是 undefined,但 stu 有一个__proto__属性,stu 调用这个属性能够间接拜访到构造函数 students 的原型对象(也就是说,stu 的__proto__属性指向的是构造函数的原型对象),请看图。
阐明(援用后面提到的文章的内容,因为很重要):
从下面的代码中能够看到,创立 stu 对象尽管应用的是 students 构造函数,然而对象创立进去之后,这个 stu 对象其实曾经与 students 构造函数没有任何关系了,stu 对象的__proto__属性指向的是 students 构造函数的原型对象。
如果应用 new students() 创立多个对象 stu1、stu2、stu3,则多个对象都会同时指向 students 构造函数的原型对象。
咱们能够手动给这个原型对象增加属性和办法,那么 stu1,stu2,stu3…这些对象就会共享这些在原型中增加的属性和办法。
如果咱们拜访 stu 中的一个属性 name,如果在 stu 对象中找到,则间接返回。如果 stu 对象中没有找到,则间接去 stu 对象的__proto__属性指向的原型对象中查找,如果查找到则返回。(如果原型中也没有找到,则持续向上找原型的原型—原型链)。
如果通过 stu 对象增加了一个属性 name,则 stu 对象来说就屏蔽了原型中的属性 name。换句话说:在 stu 中就没有方法拜访到原型的属性 name 了。
通过 stu 对象只能读取原型中的属性 name 的值,而不能批改原型中的属性 name 的值。stu.name =“李四”; 并不是批改了原型中的值,而是在 stu 对象中给增加了一个属性 name。
请看上面代码(在下面提到的文章中做了小幅度批改,更有助于了解)
<body>
<script type="text/javascript">
function students () {}
// 能够应用 students.prototype 间接拜访到原型对象
// 给 students 函数的原型对象中增加一个属性 name 并且值是 "张三"
students.prototype.name = "张三";
students.prototype.age = 20;
var stu = new students();
/*
拜访 stu 对象的属性 name,尽管在 stu 对象中咱们并没有明确的增加属性 name,然而
stu 的__proto__属性指向的原型中有 name 属性,所以这个中央能够拜访到属性 name
就值。留神:这个时候不能通过 stu 对象删除 name 属性,因为只能删除在 stu 中删除的对象。*/
alert(stu.name); // 张三
var stu1 = new students();
alert(stu1.name); // 张三 都是从原型中找到的,所以一样。alert(stu.name === stu1.name); // true
// 因为不能批改原型中的值,则这种办法就间接在 stu 中增加了一个新的属性 name,而后在 stu 中无奈再拜访到
// 原型中的属性。stu.name = "李四";
alert(stu.name); // 李四
// 因为 stu1 中没有 name 属性,则对 stu1 来说依然是拜访的原型中的属性。alert(stu1.name); // 张三
</script>
</body>
三、与原型无关的几个办法
- prototype 属性
prototype 存在于构造函数中 (其实任意函数中都有,只是不是构造函数的时候 prototype 咱们不关注而已),他指向了这个构造函数的原型对象。
-
constructor 属性
constructor 属性存在于原型对象中,他指向了构造函数
如上面代码:
<script type="text/javascript">
function students () {}
alert(students.prototype.constructor === students); // true
</script>
<span style=”color:#ff0000;”> 咱们依据须要,能够 students.prototype
属性指定新的对象,来作为 students 的原型对象。然而这个时候有个问题,新的对象的 constructor 属性则不再指向 students 构造函数了。
</span>
<span style=”color:#ff0000;”>
</span>
3.__proto__
属性 (留神:左右各是 2 个下划线)
用构造方法创立一个新的对象之后,这个对象中默认会有一个属性__proto__, 这个属性就指向了构造方法的原型对象。
到此为止,JS 的原型的根底就是这些了,如果有看不懂的请间接评论在上面,有对于 JS 原型更深刻的一些用法,理论用到的时候再进行分享。
本文由 mdnice 多平台公布