面向对象的思想就是 把我们想干的每一件事情都抽象成一个个对象,举个例子,比如我们想盖一个房子,那么这个房子就是一个对象,这个对象有一些属性,比如这个房子的面积,这个房子的位置,这个房子的价格。这个房子还有一些功能,比如居住,那么这个就相当于对象的一些方法,如果使用面向过程的思想来做这件事,那么我们每次盖一个房子,我们都需要设置这个对象的面积,位置,价格,并且会重复性的表述 这个房子有一个居住的功能,这些重复性的工作显然不是我们想做的,如果我们使用面向对象的思想来做这件事情 ,那么我们可以把房子抽象成 一个对象, 所有的房子不管是北京的房子,还是上海的房子,那么他们都有面积,价格,位置这些属性,他们还有一个公共的功能那就是居住,这样的话我们把这些公共的属性和方法写在这个对象的prototype原型之中,把一些私有的属性通过this指向每一个子级别的对象当中去,这样就避免了代码的重复也提高了程序的性能,下面是例子。
var cat1={};
cat1.name="黑猫"
cat1.color="黑色"
var cat2={};
cat1.name="白猫"
cat1.color="白色"
这就是一个面向过程的编程,每次我们新创建一个对象的时候 就会重复以上步骤,为了简化这些,我们考虑用一个函数来封装,然后通过函数的调用来达到复用的目的。
function Cat(name,color){
return {
this.name=name,
this.color=color
}
}
var cat1= Cat("黑猫",“黑色”);
var cat2=Cat("白猫",“白色”);
截止到这一步 其实还是一个面向过程的编程,只不过我们是通过函数的封装来避免了代码的重复,并没有质的变化。也就是说cat1和cat2是没有任何关系的,那么下面我们来通过面向对象这种全新的思想来进行这件事情,在进行面向对象编程之前我们先弄清一些概念。
1.构造函数
个人理解构造函数最直观的表现就是用new调用的函数,new调用也是函数的一种调用方式,函数不调用不会执行,在调用这一方面,new调用和普通的函数调用是没有区别的,但是区别在于,通过new调用 js自动生成了一个和这个函数体同名的对象,也就是说new调用一共有两个作用,第一调用函数执行函数,第二生成一个和函数体同名的对象,注意new调用的时候 函数的名的首字母一般都是大写的,这是为了区别普通函数和构造函数。OK,理解了这些之后,那我们接下来聊面向对象编程。
2.构造函数中的this 指向问题。
this指向个人总结常见的大概分为三种情况,第一在定时器,延时器,全局函数中,this是指向window的。第二,在构造函数中,this是指向构造函数new出来的这个实例化对象的。第三,在调用方法的过程中,this是指向方法所属的那个对象的。
在上述的编程思想中,cat1和cat2是没有任何关系的,因为我们可以看到,cat1和cat2 其实是分别调用了两次Cat函数 来生成的两个对象,但实际上他们有没有关系呢,答案是肯定的,因为他们都属于猫这个物种,再往大点说,猫,狗,老虎,狮子,这些看似没有关联的东西,他们不也都是属于动物这个物种吗。所以猫这个物种是cat1和cat2的关系,动物这个物种就是猫,狗,狮子,老虎,他们的关系。那么,通过这层关系,我们就可以把他们这个公共的关系抽成一个对象,个人理解也就是我们可以把它们放在同一个父级当中去,那么还以上述cat1和cat2为例,我们创造一个公共的父级对象Cat
function Cat(name,color){
this.name=name,
this.color=color
}
var cat1=new Cat("黑猫","黑色")
var cat2=new Cat("白猫",“白色")
那么我们来观察一下这样写和上面的写法有什么区别,
区别一:我们的Cat函数内部没有使用return来返回一个对象,而是通过this来做了一些指向性的操作;
区别二:我们调用函数Cat的时候不是普通的函数调用,而是通过new关键字来调用的。
好,我们现在来分析一下这些不用的地方会有什么作用。
我们在上面总结构造函数的时候提及过,函数的new调用起到了两个作用,第一是调用函数,第二是生成了一个和函数体同名的对象,并且我们在总结this指向的时候提到过,在构造函数中this是指向new出来的这个实例化对象的,那么在这个地方我们两次对Cat函数的new调用,并且分别声明了两个变量cat1和cat2的表示我们所new出来的这两个对象,虽然这两个对象的名字都叫Cat,但是这两个对象并不相同,因为他们的属性值不同,一个黑猫一个白猫,并且这两次调用过程中的this就分别指向了自己的实例化对象,相当于做了一个绑定。
截止到目前为止,我个人理解我们已经是面向对象编程了,因为我们我们通过Cat对象把cat1和cat2做了一个关联,他们都属于父级对象Cat的范畴内,有着共同的关联,但是却有着自己不同特点,也就是说他们都属于猫这个物种,但他们各自是黑猫和白猫。
这种编程思想还有一个好处就是,当有一些公共的方法的时候 我们可以把这个方法写在父级对象的原型当中去,也就是通过prototype来实现,比如如果使用面向过程来编程,当我们需要给这两个猫都添加一个捉老鼠的本领的时候就需要这样写
function Cat(name,color){
return {
this.name=name,
this.color=color,
this.eat=function(){console.log("捉老鼠")}
}
}
var cat1= Cat("黑猫",“黑色”);
var cat2=Cat("白猫",“白色”);
cat1.eat();
cat2.eat();
这样写有一个很大的缺点,那就是明明这个方法是两个函数都有的,但是我们却不得不分别的执行,这种事不利于性能提高的,这个时候 面向对象的编程方法中有一个prototype的东西可以很好的帮我们解决这个问题,
由于我们的cat1和cat2都属于Cat这个父级对象之中,那么我们可以在这个父级对象的原型也就是prototype中写上这样的一个eat方法,那么当我们分别new调用的时候子级对象就会分别继承父级的这个方法。
function Cat(name,color){
this.name=name,
this.color=color
}
Cat.prototype.eat=function(){
console.log("捉老鼠")
}
var cat1=new Cat("黑猫","黑色")
var cat2=new Cat("白猫","白色")
cat1.eat()
cat2.eat()
这样写的话就提高了我们的代码性能。
以上就是个人在看了阮一峰关于面向对象的博客解释之后的个人理解,我只是一个前端初学者,理解能力有限,并且是参考阮一峰大神的博客。在此附上阮一峰网络日志的链接,各位网友可以去阮大神那里看一下更精妙的讲解
阮一峰网络日志链接:http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_encapsulation.html