面向对象
2015-06-22 20:28 在web学习路上 阅读(382) 评论(0) 收藏 举报现在看各种招聘的要求都是需要应聘者有面向对象的开发经验,所以js中面向对象的技术相当重要,需要熟悉掌握。
首先对象叫什么,什么叫面向对象的编程,什么是面向对象?百度一下。吧啦吧啦说了一堆对面向对象的解释,最后总结到一句:“面向对象是一种对现实世界理解和抽象的方法”。“起初,“面向对象”是专指在程序设计中采用封装、继承、多态等设计方法”。这三个词我感觉学习了一些js基本概念后,应该是很容易就能理解了。
封装,可以简单理解为,将需要做的事情定义成为一个具有参数的函数,只对外提供传参数的接口,方便多次调用来处理某些参数不同,但实际过程一样的事情。
function fn(a){alerta;}; 最简单的封装,传什么弹什么。
类和继承,在js里面的实现可以通过构造函数,原型来实现。将需要继承的属性,方法写在原型上,创建出来的实例对象就有个属性指向构造函数的原型,能够获取到上面的属性和方法。
functionPerson(name){
this.name =name;
}
Person.prototype.getName= function(){
alert(this.name);
};
var person1 =new Person(‘Paul’);
这个就是最简单的继承了。新对象person1继承了Person的getName方法。当然如果要是想问为什么这样就能继承,这个我也说不清楚,估计只能去js的底层代码去找答案,js就是有这种特性。我,作为新人,感觉现在不要去考虑“为什么能”的问题,目前学习阶段最重要的是掌握js是“怎么做到”的,我们要了解上面写了继承的代码,js究竟做了哪些事情呢。这个需要了解的东西就多了:函数声明;原型(定义,特性,类型….);new操作符;函数表达式;this指向,如果子类继承父类,再学点call,apply等改变指向的方法等等等…..但是都已经开始考虑面向对象了,这些基础部分应该十分也能说个六七分吧。
多态性的定义是:同一操作作用于不同的类的实例,将产生不同的执行结果。很明显啊,如上面的例子。
var person1 =new Person(‘Paul’);
var person2 =new Person(‘Jack’);
person1.getName(); //’Paul’
person2.getName(); //’Jack’
调用了同样的方法,但是结果不同,实例是多态的,结果也是多态的。当然我这里只是举了最简单的例子,貌似还有什么静态多态,动态多态什么的,我没别的语言基础,确实也还搞不明白。
好了。现在看到这里,再思考下面向对象的概念:对现实世界理解和抽象的方法。什么现实世界?简单说就是我们看到的东西。对现实的理解和抽象?就是将看到的同类的东西概括出来。
比如,我们走在大街上,看到一辆红色兰博基尼以180km/h的速度的飞驰而过。然后我一拐弯,又看到一辆黄色的夏利停在路边。好了,有个需求,描述一下看到的东西。
var car1 = newObject();
car1.name = ‘兰博基尼’;
car1.speed =180;
car1.color =‘red’;
car1.action =function(){
return( ‘以’+this.speed + ‘km/h的速度前行’);
}
var car2 = newObject();
car2.name = ‘夏利’;
car2.speed = 0;
car2.color = ‘yellow’;
car2.action =function(){
return( ‘以’+this.speed + ‘km/h的速度前行’);
}
好吧,其实谁都知道,这样肯定写麻烦了,应该封装起来,方便下次调用。
function newCar(name,speed,color){
var car = newObject();
car.name =name;
car.speed =speed;
car.color =color;
car.action =function(){
return( ‘以’+this.speed + ‘km/h的速度前行’);
}
return car;
}
恩,现在方便多了,每次见到个新车,只要传入参数运行一次就行了。写到这里,我们先做一件事情,回顾下我们刚才写上面的代码,还有封装了一个函数时候,我们的思维过程。我看到了一辆车,车有车的名字、颜色、速度,行为。我每次描述一辆新车,我都要重新全部描述一遍,所以我封装了一个函数来方便描述。突然一想,咦我这也不是描述了一类事物么,都是车,这不也是类么,而且,调用方法的结果也是不一样,多态的啊?哈哈,说真的,看面向对象的类,还有这里的这个“类”,我一开始也纠结了好久,有什么区别,都是描述的一类东西啊。
这里先不考虑区别,我们来看下面向对象的写法,那就是直接创建类。
function Car(){
this.name =name;
this.speed =speed;
this.color =color;
}
Car.prototype.action= function(){
return( ‘以’+this.speed + ‘km/h的速度前行’);
}
我们现在来考虑下我们写这段代码时候的思维过程。我需要描述所见到的车,于是我就想,有一类东西叫车,车有车名,颜色,速度,还有行为。这些属性都是不同的车是不同的,但是所有车都具有这些属性。所以我就将这些属性概括出来,然后创建成了类的属性。
好的,到这里,我们先不比较代码,我们先来比较下我们写上面两种代码时候的思维过程。第一种:
我有个需求(描述见到的车)——见到兰博基尼我开始描述(兰博基尼,红,180,正在跑)——见到夏利我开始描述(夏利,黄,0,以0的速度在跑)——后面还可能见到更多车…
第二种:
我有个需求(描述见到的车)——我先将想了下车有什么属性(车是一类东西,有颜色,名字,速度,行为)——我封装了一个构造函数——描述见到车调用即可…
写到这里,我觉得,很多人最大的疑问应该是,第一种方法明明是我封装了函数,然后见到一个新车就调用一次就行啊,你怎么没把封装的函数写进去呢?你写的第二种本质上也是封装了一个函数,见到一个车就new一次啊。
好的,这里我们再仔细想一下,我们封装第一种函数的时候,我们想的是什么。我知道很多人都可以做到先封装函数然后调用来提高效率,但是请仔细想一下“封装函数的时候,我们到底想的是什么?”。我需要描述看到的车,我看到了兰博基尼,但我为了方便,开始封装函数:兰博基尼有自己的颜色,封装进来;兰博基尼有自己速度,封装进来….好了,将属性概括完了,函数封装完了,以后调用就行了。
很明显,第一次的时候,我们的着眼点是单辆车,后面的函数封装newCar其实也是从单个或者2个具体的实例中概括出来的,是我们为了应付不同实例车的同一属性的不同属性值,为了方便而封装的。我们的思维是,先找到实例属性值不同的属性(颜色,速度等等),然后概括出来封装。
第二次的时候,我们着眼点是车是一类东西,所有的车都有颜色,速度等等共有的属性。一开始我们就着手概括起一类事物的共有的属性来了。
好了,是不是看清楚了,我们思维的出发点是不同的。一种是少数实例上属性值不同的属性,另一种是概括出一类事物都具有的属性。
其实,写了这么多,我总感觉实际上普通的过程式的函数,能够概括出来封装起来,就已经有了面向对象的雏形了,也只能叫雏形,因为并没有真正面向对象写法的优点。就像上面的newCar函数,虽然是从面向过程的单个车描述概括出来的,但它其实也可以描述部分车了。写到封装这种程度,其实我感觉应该是处于一种面向过程到面向对象的过渡阶段了。我们要做到面向对象思维,就是要改变我们看事物的想法。再举个例子,描述运动。面向过程的思维是:物体要动起来,运动的物体不同,速度不同,距离不同。。。。而面向过程的思维是:物体运动,需要具有的属性有运动的对象,速度,距离。。。。这下应该明白很多了吧。放到编程中去就是,思维出发点,一个是多个实例不同的属性,另一个就是类的属性。
浙公网安备 33010602011771号