欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-01-28 22:01:40
...


初见原型链

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

    <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>

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

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

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

prototype/__proto__

prototype

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

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

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

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

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

__proto__

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

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

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

可以这么理解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>
前端攻城狮---js对象的高级使用(2)前端攻城狮---js对象的高级使用(2)

结果:执行上述代码,会弹出内容是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就算是找到头了。

原型链应用

效果如下 行走的小女孩 

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

利用面向对象的思维,学一个方法,在方法里去构建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对象的高级使用(2)


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