前端攻城狮---js对象的高级使用(2)


初见原型链

什么是原型链?我们先不来解释定义,我们先来看看下面几个例子。

    <script type="text/javascript">
      function Student(){
        this.job = "student";
        this.doing = function(){alert("哈哈")};
      }
      var xiaoming = new Student();
      xiaoming.doing();
      console.log(xiaoming.toString());
      console.log(Student);
      console.log(xiaoming);
    </script>


xiaoming对象调用了一个doing()方法,效果就是弹框并且上面有文字就是哈哈。试问为什么会弹框?方法谁给的?toString()方法哪来的?为什么xiaoming可以调用toString()方法?toString()方法是谁的?

首先xiaoming对象是有Student方法new出来的,所以在xiaoming的构造方法里有Student方法里的所有的属性和方法,所以可以调用到Student的doing方法。那么toString()方法是谁的?我可以负责任的告诉你是object来的?那么奇怪了,我代码里压根就没有object这几个字母,你跟我说object来的?接下来我们来引出这个对象prototype和__proto__

prototype/__proto__

prototype

prototype是函数的一个属性,它指向的是构造函数的原型,里面包含了函数的相关信息,所有函数都有prototype。我们来输出一下


我们可以看到第一个大括号里面其实现实的是构造函数。

constructor表示的是构造函数的一些信息,我们可以看到arguments,caller,length,name等信息

__proto__则表示该对象的原型对象,就是object

__proto__

当你通过函数去new一个对象,那么该对象会有个__proto__属性,该属性是指向被构造函数的prototype属性,也就是指向自己的原型对象。

我们可以通过输出日志来看看prototype和__proto__的值。

可以这么理解Student.prototype是Student的原型,Student.prototype是xiaoming的原型对象,xiaoming.__proto__指向的是Student.prototype,所以xiaoming.__proto__等同于Student.prototype。我们来整理一下它们的关系

              prototype
     Student---------------> Student.prototype
                             ↑             

              xiaoming-----_proto_ 

        构造函数的prototype指向谁,那么new出来的对象的__proto__就指向谁。

**************************************

原型链

以上介绍了prototype __proto__的概念,prototype表示原型,那么链的概念主要有__proto__来实现,组合起来就是原型链,下面来解释一下原型链的概念与应用

怎么体现呢?下面来一段demo

  <script type="text/javascript">
      function Student(name){
        this.job = "student";
        this.name=name;
        this.doing = function(){alert("哈哈")};
      }
      Student.prototype.hobby = function(){
        alert("aihao");
      };
      var xiaoming = new Student("xiaoming");
      console.log("Student.prototype");
      console.log( Student.prototype);
      console.log("xiaoming");
      console.log(xiaoming);
      console.log("xiaoming.__proto__");
      console.log( xiaoming.__proto__);
      xiaoming.hobby();
    </script>

结果:执行上述代码,会弹出内容是aihao的弹框

我们可以看到,我们没有在Student的构造方法里去添加hobby方法,而是通过prototype方式添加,通过日志可以看到hobby方法和constructor同级,所以在xiaoming的构造方法里没有hobby的方法,若要调用此方法需要通过__proto__去找。这就触发了链式的关系,流程如下xiaoming要调用hobby方法,但是自己在构造方法中找不到该方法,则会通过xiaoming.__proto__去查找hobby方法,若xiaoming.__proto__里还找不到则继往xiaoming.__proto__(Student.prototype)的__proto__去向上找,直到找到最顶还是找不到则没有。

正如之前提的一个问题,toString方法是哪来的?首先xiaoming的构造方法里没有toString方法,那么会往上找先找到xiaoming的原型对象-->xiaoming.__proto__,若还找不到toString方法,则会再网上找,也就是xiaoming.__proto__的原型对象的原型对象,也就是object,最后找到了toString方法,从而调用。

那么__proto__就引出了原型链的概念,其实原型链是一个动词,是一个操作。有很多个原型构成的链,当需要查找或调用一个函数的时候,先会在该对象的构造方法中去查找,若没有则会去查找该对象的原型__proto__,若还是没有则会继续向上找,一直到到object就算是找到头了。

原型链应用

效果如下 行走的小女孩 


利用面向对象的思维,学一个方法,在方法里去构建dom对象,对通过prototype去添加公共方法,将对象添加到数组中,通过定时器让他走起来。

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<style type="text/css">
	   * {
	   	 padding: 0;
	   	 margin: 0;
	   }
	   html,body {
	   	   height: 100%;
	   }
	   div.girl {
	   	   width: 79px;
	   	   height: 108px;
	   	   background:  url(aisidier.png) 0 -216px no-repeat;
	   	   position: absolute;
	   }

	   div.end {
	   	   border: 2px solid #000;
	   	   position: absolute;
	   	   top: 0;
	   	   left: 1000px;
	   	   height: 100%;
	   }


	</style>
</head>
<body>
	<div class="end"></div>
	<script type="text/javascript">
        //  如何设计对象 女孩
        function Girl() {
        	 this.x = 0; // 水平距离
        	 this.y = parseInt(Math.random()*(document.documentElement.clientHeight-108)); //竖直距离
        	 this.speed = parseInt(Math.random()*10)+1;// 速度
        	 this.step = 0; // 第几帧
             this.isMove = true; 
        	 // 上DOM树
        	 this.init();
             // 绑定事件
             this.bindEvent();
             Girls.push(this);// 存放所有new出来的实例
        }
        // 方法定义在原型上
        Girl.prototype.init = function() {
        	this.dom = document.createElement("div");
        	this.dom.className = "girl";
        	document.body.appendChild(this.dom);
        }
        Girl.prototype.update = function() {
               // 判断自己的运动状态
               if(!this.isMove) return;
        	   var that = this;
        	  //console.log(that.x);   	
                that.x += that.speed;
                that.step++;
                if(that.step>7) {
                	that.step = 0;
                }                
                if(that.x>1000) {
                	that.goDied();
                }                 
                that.dom.style.left = that.x + "px";
                that.dom.style.top = that.y + "px";
                that.dom.style.backgroundPosition = -that.step*79+"px -216px";
        }  
        Girl.prototype.goDied = function() {
             // 下树
             document.body.removeChild(this.dom);
             // 从数组中删除自己
             for(var i=0; i<Girls.length; i++) {
                if(Girls[i]== this) {
                    Girls.splice(i,1);
                }
             }
        }
        Girl.prototype.bindEvent = function() {
            var that = this;
            that.dom.onclick = function() {
                that.isMove = !that.isMove;
            }
        }
        var Girls = [];
        // 让数组中的所有女孩运动
        setInterval(function() {
            for(var i=0; i<Girls.length; i++) {
                Girls[i].update();
            }  
        },20);
        new Girl();
        new Girl();
        new Girl();
        new Girl();
        new Girl();
        new Girl();
	</script>
</body>
</html>
最后在附上一张小女孩的图片



原型链已讲完,接下来会来讲js对象的一些操作符,如有表达错的请谅解,并请提出指出,且修改错误,望能共同进步。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值