1、面向对象和面向过程的区别
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;
面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。(使用对象时,只关注对象提供的功能,不关注其内部细节) 面向对象是一种思想,并非只有编程中能用到,任何事都可以用到
例如五子棋,面向过程的设计思路就是首先分析问题的步骤:
1、开始游戏,
2、黑子先走,
3、绘制画面,
4、判断输赢,
5、轮到白子,
6、绘制画面,
7、判断输赢,
8、返回步骤
9、输出最后结果。
把上面每个步骤用分别的函数来实现,问题就解决了。
而面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为:
1、黑白双方,这两方的行为是一模一样的,
2、棋盘系统,负责绘制画面,
3、规则系统,负责判定诸如犯规、输赢等。
2、面向对象的三个基本特征
1>、封装 >不考虑内部实现,只考虑功能使用
封装是面向对象的特征之一,是对象和类概念的主要特性。封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
2>、继承 // “继承”(Inheritance)和“组合”(Composition) >从已有对象上,继承出新的对象
继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
3>、多态 // 有二种方式,覆盖,重载
覆盖,是指子类重新定义父类的虚函数的做法。
重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。
抽象是面向对象的特殊特征:
4>、抽象 //抓住核心问题 忽略一个主题中与当前目标无关的那些方面
3、关于this
总之记住一个原则,谁调用,this 就指向谁 || 当前使用事件的对象/obj 指使用该方法的对象;
- window.onload=function(){
- var oBox=document.getElementById('box');
- //第一种写法
- oBox.onclick=function (){
- alert(this); //当前使用事件的obj 对象 弹出oBox
- };
- //第二种写法
- var arr=[4,5,6];
- arr.a=55; //arr.a 代表当前对象 数组的属性a
- arr.sum=function(){ //数组arr的sum方法
- alert(this.a); //使用该方法的对象 弹出数组当前的a的值 当没有.a时弹出的是数组对象本身的值
- };
- arr.sum(); //总结: 看当前的function是属于谁 那么this 指的是当前的值
- //第三种
- function aa(){ //前面不写的情况下 默认是window 这种写法
- alert(this); //window.aa=function(){};
- }
- aa(); //调用后弹出 object.window
- //不要在已有的系统的对象上面添加方法 属性 自己构造对象 否则会覆盖原本系统的对象
- //如: Array()获取一组数组 Date()获取时间
- //可以使用object 这是空对象
- };
不要在已有的系统的对象上面 添加方法或者属性 自己构造对象 否则会覆盖原本系统的对象
如: Array()获取一组数组 Date()获取时间
但是可以用 object 这是空对象 所以能用Object 构造方法
需要注意的是: 代码中this的第三种写法 function aa(){alert(this) }
- window.aa=function(){alert(this)};
前面不加 window 那么直接声明函数 aa 弹出当前的this 的话 那this 指的是window (当然 如果加了 那肯定也是)
4、对象的组成
1>方法——函数:过程、动态的
2>属性——变量:状态、静态的
对象的构成
- <script type="text/javascript">
- var a = 12; //这是变量 *
- //alert(a);
- var arr=[1,2,3,4,5,6]; //这是一个数组 *
- arr.b=60; //属性: 属于一个数组<对象>
- //alert(arr.b);
- function sum(){ //函数
- alert(88)
- }
- sum(); //调用函数
- arr.sum=function(){ //方法 属于一个数组<对象>
- alert(99);
- };
- arr.sum(); //调用方法
- </script>
>属性:变量 无主的
>方法:函数 有主的
里面写的例子是数组Array 对象 数组对象是系统的对象 构建方法的原则是 不要在系统的对象上加方法(会覆盖系统对象的方法), 所以需要自己去构造对象. 然后在对象上加自己想要的方法.
构造对象最初的原型:
- //Objece构造对象1
- var obj= new Object(); //声明变量
- obj.name='张三'; //变量的属性
- obj.sex ='男'; //变量的属性
- obj.showName=function (){ //方法:属于对象
- alert(obj.name);
- };
- obj.showSex=function (){ //方法
- alert(obj.sex);
- };
- obj.showName(); //调用方法
- obj.showSex(); //调用方法
但是我们如果同时需要弹出另一个人的信息呢? <又要重新写一次代码>造成代码块的重复 代码冗余
- //Objece构造对象2
- var obj2= new Object(); //声明变量
- obj2.name='李四'; //变量的属性
- obj2.sex ='女'; //变量的属性
- obj2.showName=function (){ //方法:属于对象
- alert(obj2.name);
- };
- obj2.showSex=function (){ //方法
- alert(obj2.sex);
- };
- obj2.showName(); //调用方法
- obj2.showSex(); //调用方法
改进一下:构造函数(该函数的功能是构造对象)
构造函数
- //构造函数 指的是构造对象的函数 简称构造函数
- function people(name,sex){ //就像警察抓贼 职责
- var obj=new Object();
- obj.name=name;
- obj.sex = sex;
- obj.showName=function (){//方法
- alert(this.name);
- }
- obj.showSex=function (){//方法
- alert(this.sex);
- }
- return obj; //重要的一步 返回obj的值 因为用到了传参
- } //实参传给形参 形参使用完后把值返回给调用
- var obj=people('张三','男'); //传参 赋值
- obj.showName(); //调用函数
- obj.showSex();
- var obj2=people('李四','女'); //传参 赋值
- obj.showName(); //调用函数
- obj.showSex();
函数能实现一样的功能 但是还是需要改进 存在bug
1、对比不相等 第一次使用定义的函数 和第二次使用定义的函数明显 不是同一个 而是生成了另一个方法(这会造成函数的重复) 系统资源的浪费 每个对象使用时 都有一个方法
- //上面两个人的信息 很显然都是构造函数 那么我对比 看是否相等
- alert(obj.showName==obj2.showName);
2、使用如Date()对象 获取当前时间 的写法 明显对比我们的函数 少了new
- var time=new Date().getDay();
传参进去的时候 加上new
- //构造函数 指的是构造对象的函数 简称构造函数(原型)
- function people(name,sex)
- {
- this.name=name;
- this.sex = sex;
- }
- people.prototype.showName=function ()
- {
- alert(this.name);
- }
- people.prototype.showSex=function ()
- {
- alert(this.sex);
- }
- var obj1=new people('张三','男');
- var obj2=new people('李四','女');
- obj1.showName();
- obj1.showSex();
- obj2.showName();
- obj2.showSex();
- //上面两个人的信息 很显然都是构造函数 那么我对比 看是否相等
- alert(obj1.showName==obj2.showName); // 结果是true
可以发现 我们函数少了代码 少了构造对象 和返回值 因为new会帮我们构造对象 且 帮我们构造一个对象
1、new 在内部帮我们构造了一个对象 var this =new Object();
2、并且会内部帮我们返回值
且注意 我们在代码中添加 prototype (原型) 类似class样式一样 添加方法,类似于行间样式
prototype 属性使您有能力向对象添加属性和方法
案例:数组的求和
- //普通的写法
- var arr=[8,8,8,8,8];
- function sum(){
- var sum=0; //用来存储结果 可以写成sum=arr[0]下标一
- for (var i=0;i<arr.length;i++) { //但是i必须从第二位数开始 不然会把第一位加进去
- sum+=arr[i];
- }
- return sum;
- }
- alert(sum());
但是这种方法只适合唯一arr数组的求和 当需要求和其他数组的时候那么我们需要重复的代码 这里我们为了说原型就直接说用原型的写法
- //使用 prototype 原型的写法
- //声明一个数组
- var arr=new Array(8,8,8,8,8);
- //构造一个求和的函数
- Array.prototype.getSum=function (){
- var sum=this[0];
- for (var i=1;i<this.length;i++) {
- sum+=this[i];
- }
- return sum;
- };
- //调用该函数
- alert(arr.getSum());
使用prototype(原型)无论谁使用函数 函数都不会重复的定义 new记得加
求最大值
- //求最大值 不使用面向对象的写法
- window.onload=function (){
- var arr=[4,8,6,7,9,10,45,80,90];
- var num=arr[0];
- for (var i=0;i<arr.length;i++) {
- if (num<arr[i]) {
- num=arr[i]
- }
- }
- alert(num);
- }
- //求最大值prototype(原型)
- var arr=new Array(2,7,9,4,6,3,8,10)
- Array.prototype.getMax=function(){
- var max=this[0];
- for (var i=0;i<this.length;i++) {
- if (max<this[i]) { //修改一下>就是求最小值
- max=this[i]
- }
- }
- return max;
- }
- alert(arr.getMax());
修改一下小于号 就是求最小值
用面向对象写选项卡案例:
下面是我先用面向过程的写法实现选项卡再修改成面向对象的写法
CSS代码:
- <style type="text/css">
- *{margin: 0;padding: 0; list-style: none;}
- #box{width: 277px; height: 300px; border: 1px solid aqua; margin: 0 auto; }
- ul{width: 280px; height: 30px;}
- ul li{padding: 0px 29px; height: 30px; text-align: center; line-height: 30px; float: left; border: 1px solid pink; box-sizing: border-box; cursor: pointer;}
- #box div{display: none; line-height: 270px; text-align: center; width: 277px; height: 270px; border: 1px solid orangered; box-sizing: border-box; font-size:60px; font-family: "microsoft yahei"; text-shadow: 4px 4px 6px black;}
- .active{background: pink; border: 1px solid palegreen; }
- </style>
HTML代码:
- <body>
- <div id="box">
- <ul id="title">
- <li class="active">新闻</li>
- <li>政治</li>
- <li>时事</li>
- </ul>
- <div style="display: block;">新闻</div>
- <div>政治</div>
- <div>时事</div>
- </div>
- </body>
Javascript代码
- //原始选项卡 可以使用
- window.onload=function (){
- var oBox=document.getElementById('box');
- var aBtn=oBox.getElementsByTagName('li');
- var aDiv=oBox.getElementsByTagName('div');
- for (var i=0;i<aBtn.length;i++) {
- aBtn[i].index=i;
- aBtn[i].onclick=function (){
- for (var j=0;j<aBtn.length;j++) {
- aBtn[j].className='';
- aDiv[j].style.display='none';
- }
- this.className='active';
- aDiv[this.index].style.display='block';
- };
- }
- };
修改成面向对象的选项卡写法
JavaScript代码如下
- function Tab(id){
- var _this=this;
- var oBox=document.getElementById(id);
- this.aBtn=oBox.getElementsByTagName('li'); //this是Object.this.aBtn
- this.aDiv=oBox.getElementsByTagName('div'); //this指的是Object
- for (var i=0;i<this.aBtn.length;i++) //this指的是Object
- {
- this.aBtn[i].index=i; //this指的是Object
- this.aBtn[i].onclick=function()
- {
- _this.fnclick(this);
- }; //_this指的是Object, this:aBtn[i]:当前使用这个事件的对象
- }
- };
- Tab.prototype.fnclick=function(oBtn)
- {
- for (var j=0;j<this.aBtn.length;j++)
- {
- this.aBtn[j].className='';
- this.aDiv[j].style.display='none';
- }
- oBtn.className='active';
- this.aDiv[oBtn.index].style.display='block';
- };
- window.onload=function ()
- {
- new Tab('box'); //因为只用一次 所以直接new 这个类 而不用var 声明对象
- };