js 添加属性_轻松理解JS中的面向对象,顺便搞懂prototype和__proto__

论坛 期权论坛     
选择匿名的用户   2021-5-22 22:06   12   0
<div style="font-size:16px;">
<p>这篇文章主要讲一下JS中面向对象以及 __proto__,ptototype和construcator,这几个概念都是相关的,所以一起讲了。</p>
<p>在讲这个之前我们先来说说类,了解面向对象的朋友应该都知道,如果我要定义一个通用的类型我可以使用类(class)。比如在java中我们可以这样定义一个类:</p>
<pre class="blockcode"><code>public class Puppy{    int puppyAge;    public Puppy(age){      puppyAge &#61; age;    }    public void say() {      System.out.println(&#34;汪汪汪&#34;);     }}复制代码</code></pre>
<p>上述代码我们定义了一个Puppy类,这个类有一个属性是puppyAge,也就是小狗的年龄,然后有一个构造函数Puppy(),这个构造函数接收一个参数,可以设置小狗的年龄,另外还有一个说话的函数say。这是一个通用的类,当我们需要一个两岁的小狗实例是直接这样写,这个实例同时具有父类的方法:</p>
<pre class="blockcode"><code>Puppy myPuppy &#61; new Puppy( 2 );myPuppy.say();     // 汪汪汪复制代码</code></pre>
<p>但是早期的JS没有class关键字啊(以下说JS没有class关键字都是指ES6之前的JS,主要帮助大家理解概念),JS为了支持面向对象,使用了一种比较曲折的方式,这也是导致大家迷惑的地方,其实我们将这种方式跟一般的面向对象类比起来就很清晰了。下面我们来看看JS为了支持面向对象需要解决哪些问题,都用了什么曲折的方式来解决。</p>
<h2 class="pgc-h-arrow-right">没有class,用函数代替</h2>
<p>首先JS连class关键字都没有,怎么办呢?用函数代替,JS中最不缺的就是函数,函数不仅能够执行普通功能,还能当class使用。比如我们要用JS建一个小狗的类怎么写呢?直接写一个函数就行:</p>
<pre class="blockcode"><code>function Puppy() {}复制代码</code></pre>
<p>这个函数可以直接用new关键字生成实例:</p>
<pre class="blockcode"><code>const myPuppy &#61; new Puppy();复制代码</code></pre>
<p>这样我们也有了一个小狗实例,但是我们没有构造函数,不能设置小狗年龄啊。</p>
<h2 class="pgc-h-arrow-right">函数本身就是构造函数</h2>
<p>当做类用的函数本身也是一个函数,而且他就是默认的构造函数。我们想让Puppy函数能够设置实例的年龄,只要让他接收参数就行了。</p>
<pre class="blockcode"><code>function Puppy(age) {  this.puppyAge &#61; age;}// 实例化时可以传年龄参数了const myPuppy &#61; new Puppy(2);复制代码</code></pre>
<p>注意上面代码的this,被作为类使用的函数里面this总是指向实例化对象,也就是myPuppy。这么设计的目的就是让使用者可以通过构造函数给实例对象设置属性,这时候console出来看myPuppy.puppyAge就是2。</p>
<pre class="blockcode"><code>console.log(myPuppy.puppyAge);   // 输出是 2复制代码</code></pre>
<h2 class="pgc-h-arrow-right">实例方法用prototype</h2>
<p>上面我们实现了类和构造函数,但是类方法呢?Java版小狗还可以“汪汪汪”叫呢,JS版怎么办呢?JS给出的解决方案是给方法添加一个prototype属性,挂载在这上面的方法,在实例化的时候会给到实例对象。我们想要myPuppy能说话,就需要往Puppy.prototype添加说话的方法。</p>
<pre class="blockcode"><code>Puppy.prototype.say &#61; function() {  console.log(&#34;汪汪汪&#34;);}复制代码</code></pre>
<p>使用new关键字产生的实例都有类的prototype上的属性和方法,我们在Puppy.prototype上添加了say方法,myPuppy就可以说话了,我么来试一下:</p>
<pre class="blockcode"><code>myPuppy.say();    // 汪汪汪复制代码</code></pre>
<h2 class="pgc-h-arrow-right">实例方法查找用__proto__</h2>
<p>那myPuppy怎么就能够调用say方法了呢,我们把他打印出来看下,这个对象上并没有say啊,这是从哪里来的呢?</p>
<div class="pgc-img">
  <img alt="fc5627ebfd64f3439897f403d3bf04f8.png" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-e1b74f50e2207866a58421339a257713.png">
</div>
<p>这就该__proto__上场了,当你访问一个对象上没有的属性时,比如myPuppy.say,对象会去__proto__查找。__proto__的值就等于父类的prototype, myPuppy.__proto__指向了Puppy.prototype。</p>
<div class="pgc-img">
  <img alt="20665b91b4e9d061399395a8958fbc86.png" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-570755e369f30727d9b396ce90dda7b5.png">
</div>
<p>如果你访问的属性在Puppy.prototype也不存在,那又会继续往Puppy.prototype.__proto__上找,这时候其实就找到了Object.prototype了,Object.prototype再往上找就没有了,也就是null,<strong>这其实就是原型链</strong>。</p>
<div class="pgc-img">
  <img alt="5d1d87c85f7070088e9aabd2c34eeeec.png" src="https:/
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP