原型链

Posted swjieyi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原型链相关的知识,希望对你有一定的参考价值。



用过JavaScript的同学们肯定都对prototype如雷贯耳,但是这究竟是个什么东西却让初学者莫衷一是,只知道函数都会有一个prototype属性,可以为其添加函数供实例访问,其它的就不清楚了,最近看了一些 javascript高级程序设计,终于揭开了其神秘面纱。

每个函数都有一个prototype属性,这个属性是指向一个对象的引用,这个对象称为原型对象,原型对象包含函数实例共享的方法和属性,也就是说将函数用作构造函数调用(使用new操作符调用)的时候,新创建的对象会从原型对象上继承属性和方法。不像传统的面向对象语言,Javascript的继承机制基于原型,而不是Class类。

1、私有变量、函数

在具体说prototype前说几个相关的东东,可以更好的理解prototype的设计意图。在了解JavaScript原型链之前,有必要先了解一下JavaScript的作用域链。JavaScript的函数作用域,在函数内定义的变量和函数如果不对外提供接口,那么外部将无法访问到,也就是变为私有变量和私有函数。

<code class="hljs javascript hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">function</span></span></span><span class="hljs-function" style="box-sizing: border-box;"> </span><span class="hljs-title" style="box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-title" style="box-sizing: border-box;">Obj</span></span></span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="box-sizing: border-box;">()</span></span></span><span class="hljs-function" style="box-sizing: border-box;"></span></span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> a=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//私有变量</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> fn=<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">function</span></span></span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="box-sizing: border-box;">()</span></span></span><span class="hljs-function" style="box-sizing: border-box;"></span></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//私有函数</span>

   
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

这样在函数对象Obj外部无法访问变量a和函数fn,它们就变成私有的,只能在Obj内部使用,即使是函数Obj的实例仍然无法访问这些变量和函数

<code class="hljs coffeescript hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-reserved" style="box-sizing: border-box;">var</span> o=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Obj();
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">console</span>.log(o.a); <span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span><span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">undefined</span>
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">console</span>.log(o.fn); <span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span><span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">undefined</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

2、静态变量、函数

当定义一个函数后通过 “.”为其添加的属性和函数,通过对象本身仍然可以访问得到,但是其实例却访问不到,这样的变量和函数分别被称为静态变量和静态函数,用过Java、C#的同学很好理解静态的含义。

<code class="hljs javascript hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">function</span></span></span><span class="hljs-function" style="box-sizing: border-box;"> </span><span class="hljs-title" style="box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-title" style="box-sizing: border-box;">Obj</span></span></span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="box-sizing: border-box;">()</span></span></span><span class="hljs-function" style="box-sizing: border-box;"></span></span>
    Obj.a=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//静态变量</span>
    Obj.fn=<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">function</span></span></span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="box-sizing: border-box;">()</span></span></span><span class="hljs-function" style="box-sizing: border-box;"></span></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//静态函数       </span>


console.log(Obj.a); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//0</span>
console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> Obj.fn); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//function</span>

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> o=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Obj();
console.log(o.a); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//undefined</span>
console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> o.fn); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//undefined</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

3、实例变量、函数

在面向对象编程中除了一些库函数我们还是希望在对象定义的时候同时定义一些属性和方法,实例化后可以访问,JavaScript也能做到这样

<code class="hljs javascript hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">function</span></span></span><span class="hljs-function" style="box-sizing: border-box;"> </span><span class="hljs-title" style="box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-title" style="box-sizing: border-box;">Obj</span></span></span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="box-sizing: border-box;">()</span></span></span><span class="hljs-function" style="box-sizing: border-box;"></span></span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.a=[]; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//实例变量</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.fn=<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">function</span></span></span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="box-sizing: border-box;">()</span></span></span><span class="hljs-function" style="box-sizing: border-box;"></span></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//实例方法    </span>
    


console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> Obj.a); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//undefined</span>
console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> Obj.fn); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//undefined</span>

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> o=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Obj();
console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> o.a); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//object</span>
console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> o.fn); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//function</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul>

这样可以达到上述目的,然而

<code class="hljs javascript hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">function</span></span></span><span class="hljs-function" style="box-sizing: border-box;"> </span><span class="hljs-title" style="box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-title" style="box-sizing: border-box;">Obj</span></span></span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="box-sizing: border-box;">()</span></span></span><span class="hljs-function" style="box-sizing: border-box;"></span></span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.a=[]; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//实例变量</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.fn=<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">function</span></span></span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="box-sizing: border-box;">()</span></span></span><span class="hljs-function" style="box-sizing: border-box;"></span></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//实例方法</span>

    


<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> o1=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Obj();
o1.a.push(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
o1.fn=;
console.log(o1.a); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//[1]</span>
console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> o1.fn); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//object</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> o2=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Obj();
console.log(o2.a); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//[]</span>
console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> o2.fn); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//function</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul>

上面的代码运行结果完全符合预期,但同时也说明一个问题,在o1中修改了a和fn,而在o2中没有改变,由于数组和函数都是对象,是引用类型,这就说明o1中的属性和方法与o2中的属性与方法虽然同名但却不是一个引用,而是对Obj对象定义的属性和方法的一个复制。

这个对属性来说没有什么问题,但是对于方法来说问题就很大了,因为方法都是在做完全一样的功能,但是却又两份复制,如果一个函数对象有上千和实例方法,那么它的每个实例都要保持一份上千个方法的复制,这显然是不科学的,这可肿么办呢,prototype应运而生。先看看对象的含义:

4 . 普通对象与函数对象

JavaScript 中,万物皆对象!但对象也是有区别的。分为普通对象和函数对象,Object ,Function 是JS自带的函数对象。下面举例说明

<code class="hljs javascript hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">function</span></span></span><span class="hljs-function" style="box-sizing: border-box;"> </span><span class="hljs-title" style="box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-title" style="box-sizing: border-box;">f1</span></span></span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="box-sizing: border-box;">()</span></span></span><span class="hljs-function" style="box-sizing: border-box;"></span></span>;
 <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> f2 = <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">function</span></span></span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="box-sizing: border-box;">()</span></span></span><span class="hljs-function" style="box-sizing: border-box;"></span></span>;
 <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> f3 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Function</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'str'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'console.log(str)'</span>);

 <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> o3 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> f1();
 <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> o1 = ;
 <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> o2 =<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Object</span>();

 console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Object</span>); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//function</span>
 console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Function</span>); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//function</span>
 console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> o1); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//object</span>
 console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> o2); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//object</span>
 console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> o3); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//object</span>
 console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> f1); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//function</span>
 console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> f2); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//function</span>
 console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> f3); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//function </span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>

在上面的例子中 o1 o2 o3 为普通对象,f1 f2 f3 为函数对象。怎么区分,其实很简单,凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象。 f1,f2,归根结底都是通过 new Function()的方式进行创建的。Function Object 也都是通过 New Function()创建的。

5、prototype原型

在JavaScript 中,每当定义一个对象(函数)时候,对象中都会包含一些预定义的属性。其中函数对象的一个属性就是原型对象 prototype。注:普通对象没有prototype,但有_ proto _属性。

原型对象其实就是普通对象(Function.prototype除外,它是函数对象,但它很特殊,他没有prototype属性(前面说道函数对象都有prototype属性))。看下面的例子:

<code class="hljs javascript hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">function</span></span></span><span class="hljs-function" style="box-sizing: border-box;"> </span><span class="hljs-title" style="box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-title" style="box-sizing: border-box;">f1</span></span></span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="box-sizing: border-box;">()</span></span></span><span class="hljs-function" style="box-sizing: border-box;"></span></span>;
 console.log(f1.prototype) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//f1</span>
 console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> f1.prototype) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Object</span>
 console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Function</span>.prototype) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Function,这个特殊</span>
 console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Object</span>.prototype) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Object</span>
 console.log(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typeof</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Function</span>.prototype.prototype) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//undefined</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

从这句console.log(f1.prototype) //f1 的输出就结果可以看出,f1.prototype就是f1的一个实例对象(这里就是f1的原型对象)。就是在f1创建的时候,创建了一个它的实例对象并赋值给它的prototype,基本过程如下:

<code class="hljs cs hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> temp = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> f1();
 f1. prototype = temp;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

所以,Function.prototype为什么是函数对象就迎刃而解了,上文提到凡是new Function ()产生的对象都是函数对象,所以temp1是函数对象。

<code class="hljs php hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> temp1 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">Function</span></span></span><span class="hljs-function" style="box-sizing: border-box;"> </span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="box-sizing: border-box;">()</span></span></span><span class="hljs-function" style="box-sizing: border-box;">;</span></span>
 <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">Function</span></span></span><span class="hljs-function" style="box-sizing: border-box;">.</span><span class="hljs-title" style="box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-title" style="box-sizing: border-box;">prototype</span></span></span><span class="hljs-function" style="box-sizing: border-box;"> = </span><span class="hljs-title" style="box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-title" style="box-sizing: border-box;">temp1</span></span></span><span class="hljs-function" style="box-sizing: border-box;">;</span></span>
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

那原型对象是用来做什么的呢?主要作用是用于继承。举了例子:

<code class="hljs javascript hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">var</span> person = <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">function</span></span></span><span class="

以上是关于原型链的主要内容,如果未能解决你的问题,请参考以下文章

js中原型和原型链理解

原型与原型链

你不知道的JS5-原型

原型原型链闭包继承

关于js原型链

介绍下Javascript原型和原型链的特点?