今天在网上看到一条关于面向对象的很形象的题目,决定转过来分享一下。

小贤是一条可爱的小狗(Dog),它的叫声很好听(wow),每次看到主人的时候就会乖乖叫一声(yelp)。

小芒和小贤一样,原来也是一条可爱的小狗,可是突然有一天疯了(MadDog),一看到人就会每隔半秒叫一声(wow)地不停叫唤(yelp)。

请根据描述,按示例的形式用代码来实现(提示关键字: 继承,原型,setInterval)。

正确答案:

<script language=”JavaScript” type=”text/javascript”>
    window.onload = function(){
        function Dog(name){this.name = name;}
        Dog.prototype = {
            constructor : Dog,
            wow: function(){
                alert(‘wow’);
            },
            yelp: function(){
                return this.wow();
            }
        }
        function CrazyDog(name){this.name = name;}
        CrazyDog.prototype = new Dog();
        CrazyDog.prototype.madYelp = function(){
            var _self = this;
            setInterval(function(){
                return _self.yelp();
            }, 2000);
        }
        var xiaoXian = new Dog(“xiaoXian”);
        var xiaoXianBtn = document.getElementById(“xiaoXianBtn”);
        xiaoXianBtn.onclick = function(){xiaoXian.yelp();}
        var xiaoMang = new CrazyDog(“xiaoMang”);
        var xiaoMangBtn = document.getElementById(“xiaoMangBtn”);
        xiaoMangBtn.onclick = function(){xiaoMang.madYelp();}
    }
</script>
 

//构造函数 myObject
//使自己的对象多次复制,同时实例根据设置的访问等级可以访问其内部的属性和方法
//当对象被实例化后,构造函数会立即执行它所包含的任何代码
function myObject(msg){
//特权属性(公有属性)
this.myMsg = msg; //只在被实例化后的实例中可调用
this.address = ‘上海’;

//私有属性
var name = ‘豪情’;
var age = 29;
var that = this;

//私有方法
function sayName(){
alert(that.name);
}
//特权方法(公有方法)
//能被外部公开访问
//这个方法每次实例化都要重新构造而prototype是原型共享,所有实例化后,都共同引用同一个
this.sayAge = function(){
alert(name); //在公有方法中可以访问私有成员
}
//私有和特权成员在函数的内部,在构造函数创建的每个实例中都会包含同样的私有和特权成员的副本,
//因而实例越多占用的内存越多
}
//公有方法
//适用于通过new关键字实例化的该对象的每个实例
//向prototype中添加成员将会把新方法添加到构造函数的底层中去
myObject.prototype.sayHello = function(){
alert(‘hello everyone!’);
}
//静态属性
//适用于对象的特殊实例,就是作为Function对象实例的构造函数本身
myObject.name = ‘china’;
//静态方法
myObject.alertname = function(){
alert(this.name);
}
//实例化
var m1 = new myObject(’111′);
//—- 测试属性 —-//
console.log(myObject.name); //china
console.log(m1.name); //undefined, 静态属性不适用于一般实例
console.log(m1.constructor.name); //china, 想访问类的静态属性,先访问该实例的构造函数,然后再访问该类静态属性
console.log(myObject.address); //undefined, myObject中的this指的不是函数本身,而是调用address的对象,而且只能是对象
console.log(m1.address); //上海 此时this指的是实例化后的m1

//—- 测试方法 —-//
myObject.alertname(); //china,直接调用函数的类方法
m1.alertname(); //FF: m1.alertname is not a function, alertname 是myObject类的方法,和实例对象没有直接关系
m1.constructor.alertname(); //china, 调用该对象的构造函数(类函数)的方法(函数)
m1.sayHello(); //hello everyone, myObject类的prototype原型下的方法将会被实例继承
myObject.sayHello(); //myObject.sayHello is not a function,sayHello是原型方法,不是类的方法

//—- 测试prototype —-//
console.log(m1.prototype); //undefined, 实例对象没有prototype
console.log(myObject.prototype); //Object
alert(myObject.prototype.constructor); //console.log返回myObject(msg),此时alert()更清楚,相当于myObject
console.log(myObject.prototype.constructor.name); //china, 相当于myObject.name;

转自:http://www.cnblogs.com/jikey/archive/2011/05/13/2045005.html

 

第二篇  

<script type=”text/javascript”>

//构造函数  Person     //其中一种类方法定义的方法
  function Person(name){
     //类变量
     this.name = name;
     this.age  = 0;

      this.gender = 0;

     this.pets = new Array();
  }

  //类setName(name)的函数
  Person.prototype.setName=function(name){
     this.name=name;
  }

  //类getName(name)的函数
  Person.prototype.getName=function(){
     return this.name;
  }

  //类pushPetsArr(item)的函数
  Person.prototype.pushPetsArr=function(item){
     this.pets[this.pets.length] = item;
  }

//构造函数 Person    //另一种类方法定义的方法
  function Person(name){
     //类变量
     this.name = name;
     this.age  = 0;
     this.gender = 0;
     this.pets = new Array();
  }

  //类setName(name)的函数
  Person.prototype = {
      setName: function(name){
          this.name=name;
      },

      //类getName(name)的函数

      getName: function(){
          return this.name;
      },

      //类pushPetsArr(item)的函数
      pushPetsArr: function(item){
          this.pets[this.pets.length] = item;
      }
  }
</script>

<script type=”text/javascript”>

 var myNameSpace = new Object(); //构造一个命名 空间myClass

 //类的属性
 myNameSpace.names=”cnscn”;
 myNameSpace.age=”30″;

 myNameSpace.ClassPersons=function(argName,argAge){ //构造类名,即构造函数
    this.names=argName;
    this.age=argAge;
 }

 myNameSpace.ClassPersons.prototype={//类方法的定义
    //方法getName()
    getName:function(){
      alert(this.names);
    }//注意这里是”逗号
     //方法setName(argName)
    setName:function(argName){
       this.names=argName;
    }
 }

 var obj=new myNameSpace.ClassPersons(“yao”, 23);
 obj.getName();
 obj.setName(“hhhh”);
 obj.getName();
alert(myNameSpace.name);

</script>

转自:http://blog.sina.com.cn/s/blog_675879000100ijui.html

 

看了这么多关于面向对象和面向过程的区别的文章,觉得下面讲的是比较浅显易懂的,所以就偷了过来,哈哈!!

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。

面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。

例如五子棋,面向过程的设计思路就是首先分析问题的步骤:1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。把上面每个步骤用分别的函数来实现,问题就解决了。

而面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为 1、黑白双方,这两方的行为是一模一样的,2、棋盘系统,负责绘制画面,3、规则系统,负责判定诸如犯规、输赢等。第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的i变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。

可以明显地看出,面向对象是以功能来划分问题,而不是步骤。同样是绘制棋局,这样的行为在面向过程的设计中分散在了总多步骤中,很可能出现不同的绘制版本,因为通常设计人员会考虑到实际情况进行各种各样的简化。而面向对象的设计中,绘图只可能在棋盘对象中出现,从而保证了绘图的统一。

功能上的统一保证了面向对象设计的可扩展性。比如我要加入悔棋的功能,如果要改动面向过程的设计,那么从输入到判断到显示这一连串的步骤都要改动,甚至步骤之间的循序都要进行大规模调整。如果是面向对象的话,只用改动棋盘对象就行了,棋盘系统保存了黑白双方的棋谱,简单回溯就可以了,而显示和规则判断则不用顾及,同时整个对对象功能的调用顺序都没有变化,改动只是局部的。

再比如我要把这个五子棋游戏改为围棋游戏,如果你是面向过程设计,那么五子棋的规则就分布在了你的程序的每一个角落,要改动还不如重写。但是如果你当初就是面向对象的设计,那么你只用改动规则对象就可以了,五子棋和围棋的区别不就是规则吗?(当然棋盘大小好像也不一样,但是你会觉得这是一个难题吗?直接在棋盘对象中进行一番小改动就可以了。)而下棋的大致步骤从面向对象的角度来看没有任何变化。

当然,要达到改动只是局部的需要设计的人有足够的经验,使用对象不能保证你的程序就是面向对象,初学者或者很蹩脚的程序员很可能以面向对象之虚而行面向过程之实,这样设计出来的所谓面向对象的程序很难有良好的可移植性和可扩展性。

引于:http://www.cnblogs.com/vegaslee/archive/2008/07/29/1255598.html

© 2012 Hedgehog Suffusion theme by Sayontan Sinha