【JavaScript从入门到精通】第二十四课 JS面向对象基础-01

此内容来自开课吧石川微信公众号

经过前面这些课的学习,大家对JS的很多内容都有了比较深入的了解。从这节课开始我们开始讲JS面向对象的内容。相信大家平时在学习工作中经常会听说到面向对象,但面向对象对于大家或许是一个非常抽象的概念。那么,应该如何认识面向对象呢?

什么是面向对象

想要说明什么是面向对象,我们先举一个简单的小例子。大家平时在使用电视的时候,可以非常轻松的使用它的各种功能,例如音量调节,电视台切换等,但是我们并不会去关心和了解电视的内部结构原理。

为什么我们不知道原理也可以使用电视呢?

因为我们只需要使用遥控器的按钮即可,内部的结构并不会影响我们对它的使用。另一个更贴近我们程序的例子是Date对象,我们之前已经多次使用了它,例如它里面的getFullYear方法可以获取当前年份,我们可以非常轻松地使用它。但我们知道它的内部工作原理吗?它是如何获取年份的?我们并不知道,但完全也不影响使用。

不了解原理的前提下,会使用功能,这就是面向对象的体现。对象在程序里是一种黑盒子,我们看不到它里面是什么,不了解它内部的结构,但却知道它表面的操作(相当于电视机的按钮)。我们在前面的学习中,已经多次体现出了这一点,除去上面的Date对象,我们曾经使用过Array对象的sort()方法进行排序,但它是通过什么方法排序的我们就不得而知了。

总的来说,面向对象是一种通用的思想,并非只有在编程中使用,面向对象的思想本身就借鉴于生活,我们做很多事的时候都会用到面向对象。

JS的面向对象

讲解了这么多关于面向对象的介绍,那么在JS里,面向对象是如何体现的呢?

我们先从面向对象编程(OOP)的特点讲起。面向对象编程有如下特性:

  • 抽象:抓住核心问题,把最主要的特征和跟问题相关的特征抽取出来。根据问题不同,抽象的方式也有不同。
  • 封装:看不到内部结构,可以使用表面的功能。
  • 继承:从父类上继承出一些方法、属性给子类,而子类也拥有一些自己的特性。使用继承可以使一个对象获得另一个对象的功能,最大程度保证了代码的重用。对于继承来说,还存在两种情况:
    • 多重继承。一个子类继承于多个父类,那么它可以获得多个父类的特性。
    • 多态。多态在JS这种弱语言意义不大,我们以后再说。

对于面向对象来说,存在编写对象的人和使用对象的人,在之前的课程里我们都扮演者使用者的角色,从现在开始我们要尝试着开始编写一些简单的对象。

JS里的对象由方法和属性组成。这里我们需要先区分一下属性和变量,函数和方法之间的区别。

var a=12;alert(a);  //变量var arr=[1,2,3,4,5,6];arr.a=12;  //属性alert(a);

实际上,属性和变量在本质上是一样的,但变量比较自由,而属性隶属于一个对象之下。类似的,当一个自由的函数隶属于一个对象之后,它就被称为方法。

function aaa()          //函数:自由{
    alert('abc');}var arr=[1,2,3,4];arr.aaa=function ()     //方法:属于一个对象{
    alert('abc');};aaa();arr.aaa();

所以属性和方法其实并不是新概念,其本质上还是我们学习过的变量和函数,在使用上也是一致的。

还有一个地方值得注意的是,我们之前使用过的this关键字,当它在对象中使用的时候,代指的就是当前对象本身。对于this来说,当前的方法属于哪个对象,那么this代指的就是哪个对象。

现在我们来尝试这么一个例子:

function show(){
  alert(this);}show();

结果如下:

【JavaScript从入门到精通】第二十四课 JS面向对象基础-01

为什么结果是window对象呢?实际上我们在JS里写这样的全局函数,都是属于window对象下的,上面的函数相当于给window加了一个show方法:

window.show=function(){
  alert(this);}

因此this关键字返回的对象是window。

比较需要注意的一点是,尽量不要在系统对象中随意添加方法和属性,否则会覆盖已有的方法和属性。

此外,JS还存在一种object对象,它没有任何功能,是一个空白对象,因此我们在实现面向对象的时候,可以向object对象上添加属性和方法,和以最大程度地避免发生冲突。

第一个面向对象程序

使用new关键字和object对象创建一个新对象,并在新对象内添加属性和方法。

var obj=new Object();obj.name='blue';obj.qq='258248832';obj.showName=function (){
    alert('我的名字叫:'+this.name);};obj.showQQ=function (){
    alert('我的QQ号:'+this.qq);};obj.showName();obj.showQQ();

效果如下:

【JavaScript从入门到精通】第二十四课 JS面向对象基础-01

这就是一个最简单的面向对象程序。对于使用这个程序的人,并不关心obj内部有什么,而是直接调用showName方法和showQQ方法来使用对象。但可以看到,我们的name和qq属性是固定的。如果我们需要很多个obj对象的时候,我们不希望再重复进行修改而是简单调用即可。因此我们使用一个函数将这段代码包裹起来。

function createPerson(name, qq)     //构造函数{
 var obj=new Object();
 obj.name=name;
 obj.qq=qq;
 obj.showName=function ()
 {
   alert('我的名字叫:'+this.name);
 };
 obj.showQQ=function ()
 {
   alert('我的QQ号:'+this.qq);
 };
 return obj;}var obj=createPerson('blue', '258248832');obj.showName();obj.showQQ();var obj2=createPerson('张三', '45648979879');obj2.showName();obj2.showQQ();

我们将姓名和qq作为函数参数传入并将obj对象作为返回值,这样就实现了我们对象的通用。我们将createPerson这类用于构造一个对象的函数称为构造函数。构造函数在结构上和普通函数没有任何区别,它与其它函数仅仅是在功能上有所不同。

工厂方式

说到在工厂工作,我们总能想到下面几个关键字:原料,加工,出厂。我们上面的构造对象的方式就被称为工厂方式,因为它的流程和在工厂工作是异曲同工的。在一开始,我们创建了一个空白对象,这就是我们用来构造对象的“原料”,接着我们给对象添加了属性和方法,这就是们对对象的“加工”,最后我们将对象返回出去供外使用,相当于对对象进行了“出厂”。

但是工厂方式存在一些小问题,导致我们在工作中无法直接去使用工厂方式来实现面向对象。

首先,使用工厂方式编写的对象,在调用的时候没有new关键字。

其次,当我们申明的对象过多时,由于工厂模式每个对象都要占据一定的储存空间,明明每个对象内的方法或属性都是一样的,依旧会浪费系统大量的资源。

如需转载,烦请注明出处:https://www.qdskill.com/javascript/4425.html

发表评论

登录后才能评论