javascript 特殊的面向对象以及继承详解(入门篇)

 学习Javascript人,大多听说一句话叫js里面一切都是对象。我刚开始接触javascript面向对象编程时候,挺乱的,我当时习惯性的把PHP的面像对象思想套用在js上面,其实js的面向对象与传统的面向对象还是有很多区别的。这里就不再去讲解基础的面向对象是什么了,看这篇文章就默认大家都知道面向对象的概念。

  首先,在目前的js版本中,依然没有引入class这个关键词,js里面没有类的概念,其他语言在实例化一个对象的时候,都是使用new 类名来得到实例,而js由于没有class,因此它的面向对象也可以理解为是一种模拟的方式。首先我们来说一下js里面的函数,js里面都函数有一个特点,就是所有的函数都有返回值,如果我们没有手动编写 return。那么函数会返回一个underfind,如果写了,则返回你写的值。这种返回值是在正常的函数调用情况下出现的。比如:

  function a(){

    return 123;

   }

  a();

此时返回123。

  function a(){

   }

  a();

此时返回underfind。

  那么,我们在调用js里面的函数时候,其实不止这一种方式,常用的还用使用call或者apply方法也可以使函数执行,这个以后再说。除此之外,我们还可以通过 new的方式来调用函数,new在js里面其实是一种运算符,但凡函数是通过它来调用的,返回值就会发生变化。如果我们在函数中没有写返回值或者返回值写的不是对象类型的数据,那么这个函数都会返回一个空对象,如果我们写的返回值是一个对象,那么则返回我们写的对象。所以只要是通过new来调用函数,返回值就变成了对象。

  js也充分利用了这一点,来模拟传统的面向对象,我们来看一个例子:

  function Obj(){

    this.name=‘小红‘;

    this.age=‘24‘;

  }

  var poeple = new Obj();

  根据我们上面说的,当我们使用new去调用函数时候,返回对象,因此我们可以得知people其实就是一个对象了。我们看到上面的代码中this.name=‘小红‘,this.age=‘24‘,这个this其实是什么呢?其实这个this就是我们返回的对象,也就是说this就是people,如果不能理解,只需记住,这是js的特点。我们接着看:

  

function Obj(){

    this.name=‘小红‘;

    this.age=‘24‘;

  }

  var poeple = new Obj();

  alert(people.name);

  alert(people.age);

  运行上述代码以后,分别弹出了小红和24,这更加确切的说明this就是people.

  但是这个this也不一定只是people,确切的说这个this是谁具体要看是谁在调用这个函数,看例子:

  function Obj(){

    this.name=‘小红‘;

    this.age=‘24‘;

  }

  Obj();

  当我这样去调用的时候,这个this指向的是谁呢?其实js是运行在浏览器中的,浏览器中有一个顶层对象叫做window,所有的变量和函数其实都是挂在他下面的,看例子:

  Obj();

  window.Obj();

  这两种写法的效果是一样的,此时没有通过new来调用,其实就是一个普通的函数,而这个函数的调用者是window,因此这个this指向window.

  所以说this的指向不是固定的,要看具体的调用方式以及是谁在调用。

  我们一般把这种用来返回的对象的函数称作构造函数,他的作用就是用来创建对象的,一般为了区分构造函数与普通函数的区别,构造函数的首字母会大写。我早期学习的时候,就把这里的构造函数与其他语言里的class弄混淆了,其实他们是不同的东西。

  第二个就是js的面向对象同样有继承的功能,只是它的继承与传统的继承方式也不一样,我个人认为也是一种模拟。首先说明一件事情,在js里面所有的对象都有一个叫做__proto__的属性,所有的函数都有__proto_的属性和prototype的属性,prototype属性对应的值是一个对象,这个对象可以保存很多东西的,中文名称叫做原型对象,看例子:

  

function Obj(){

    this.name=‘小红‘;

    this.age=‘24‘;

  }

  Obj.prototype.job=‘老师‘;

  var poeple = new Obj();

  alert(people.job);// 弹出 老师

  刚才已经说过,此时的people就是一个对象,而Obj是一个函数,people是Obj的一个实例对象,他们之间肯定是有关系的,既然people是一个对象,那么他肯定有_proto_属性,这个属性其实指向了Obj的prototype,再详细说一下,people的__proto__保存的是一个地址,这个地址指向的是people的构造函数Obj的prototype属性。所以程序运行到people.job的时候,people这个对象在自己的属性里面开始寻找job这个东西,但是木有找到,于是接下来他就找到了自己的__proto__,顺着里面的地址找到了Obj.prototype,在这里发现了job,然后呢,他就把job的值给弹了出来。这一连串的动作专业术语叫做原型链查找,那为什么要说这个呢,主要是因为js的继承有一种方式就叫做原型继承。那上面已经把对象和构造函数的在原型方面的联系说清楚了。那么接下来我们就说一下js的原型继承,看例子:

  

function a(){

    this.name=‘小红‘;

    this.age=‘24‘;

  }

  

function b(){

    this.job=‘小红‘;

    this.sex=‘男‘;

  }

b.prototype=new a();

var c = new b();

alert(c.name);//小红

  以上代码,做了一个功能,把b的原型对象修改成了a的实例对象,这时b的实例对象去访问name属性时候,首先在自身查找,没有发现,于是去他的构造函数b的原型里面去查找,而此时b的原型就是一个a的实例对象,a的实例对象当然有name和age属性了,因此就访问到了。这种方式成为原型继承,有一个小问题,就是这样直接把对象赋值给prototype,修改了prototype里面的constructer属性,constructer属性后面再说。
  除了原型继承以外,还有一些方式也可以实现继承,最常用的就是call和apply方法,解释这个问题还需要了解另外一个特性,我们上面已经看到了,call方法可以用来调用函数,其实他的功能不止于此,最核心的功能就是改变this指向,我们来看例子:

此时,对象c拥有 name age self三个属性,前面两个就是继承下来的了。

其实,真实的编写过程,往往把上述两种继承方式同时使用,当然还有一些其他的继承方式,大家可以自己去网上查查。

这里说一下,上面那种原型继承法有一点点问题,直接把对象赋值给原型会导致原型里面的constructor出现错误,这个constructor实际上用来保存对象的构造函数的,也就是说一个对象是由那个构造函数实例化而成的,那么这个constructor就代表那个构造函数。举例:

  

function a(){

    this.name=‘小红‘;

    this.age=‘24‘;

  }

var b = new a();

alert(a.constructor); //  打印出来的就是整个函数

如果直接把对象赋值给原型,这个constructor值就会被修改,所以,为了保险起见,很多人都会手动加上一句 a.prototype.constructor = a;

这里没有介绍更多的面向对象的东西,写的过程中也有遇到疑惑的,如果有错误的话,请大家多多指教!

时间: 2024-10-11 15:44:49

javascript 特殊的面向对象以及继承详解(入门篇)的相关文章

JavaScript中的面向对象编程,详解原型对象及prototype,constructor,proto,内含面向对象编程详细案例(烟花案例)

面向对象编程: 面向:以什么为主,基于什么模式 对象:由键值对组成,可以用来描述事物,存储数据的一种数据格式 编程:使用代码解决需求 面向过程编程: 按照我们分析好的步骤,按步骤解决问题 优点:性能比面向对象高,适合跟硬件联系很紧密的东西 缺点:没有面向对象那么容易维护,复用,扩展 面向对象编程: 把事务分解成一个个对象,然后由对象之间分工与合作,分工明确,每一个对象都是功能中心 面向对象特性:封装性.继承性 .多态性 封装性:将一个功能封装起来,小封装 将多个函数封装起来,整体封装起来形成一个

Redis详解入门篇

[本教程目录] 1.redis是什么 2.redis的作者 3.谁在使用redis 4.学会安装redis 5.学会启动redis 6.使用redis客户端 7.redis数据结构 – 简介 8.redis数据结构 – strings 9.redis数据结构 – lists 10.redis数据结构 – 集合 11.redis数据结构 – 有序集合 12.redis数据结构 – 哈希 13.聊聊redis持久化 – 两种方式 14.聊聊redis持久化 – RDB 15.聊聊redis持久化 –

Kotlin——从无到有系列之中级篇(四):面向对象的特征与类(class)继承详解

如果您对Kotlin很有兴趣,或者很想学好这门语言,可以关注我的掘金,或者进入我的QQ群大家一起学习.进步. 欢迎各位大佬进群共同研究.探索 QQ群号:497071402 进入正题 在前面的章节中,详细的详解了类的使用,但是由于篇幅的限制,关于类的很多特性都没有讲解到.今天在这篇文章中,详细的讲解Kotlin中类的特性.如果您对Kotlin中的类还没有一个整体的了解的话,请参见我上一篇文章Kotlin--类(class)详解 众所周知,Kotlin是一门面向对象的开发语言.那么他也有面向对象语言

JavaScript学习总结(十一)——Object类详解

一.Object类介绍 Object类是所有JavaScript类的基类(父类),提供了一种创建自定义对象的简单方式,不再需要程序员定义构造函数. 二.Object类主要属性 1.constructor:对象的构造函数. 2.prototype:获得类的prototype对象,static性质. 三.Object类主要方法 1.hasOwnProperty(propertyName) 判断对象是否有某个特定的属性.必须用字符串指定该属性,例如,obj.hasOwnProperty("name&q

JavaScript原生对象属性和方法详解——Array对象 转载

length 设置或返回 数组中元素的数目. 注意:设置 length 属性可改变数组的大小.如果设置的值比其当前值小,数组将被截断,其尾部的元素将丢失.如果设置的值比它的当前值大,数组将增大,新的元素被添加到数组的尾部,它们的值为 undefined.所以length不一定代表数组的元素个数. var arr = new Array(3) arr[0] = "John" arr[1] = "Andy" arr[2] = "Wendy" cons

JavaScript表单序列化的方法详解

本文介绍下,在javascript中实现表单序列化的方法,通过实例加深理解,有需要的朋友参考下吧. 在JavaScript中,可以利用表单字段的type属性,连同name和value属性一起实现对表单的序列. 首先,我们来了解下在表单提交期间,浏览器是怎样将数据发送给服务器的.对表单字段的名称和值进行URL编码,使用和号(&)分割.不发送禁用的表单字段.只发送勾选的复选框和单选按钮.不发送type为"reset"和"button"的按钮.多选择框中的每个选中

HTML中javascript的<script>标签使用方法详解

原文地址:HTML中javascript的<script>标签使用方法详解 只要一提到把JavaScript放到网页中,就不得不涉及Web的核心语言--HTML.在当初开发javascript的时候,Netscape要解决的一个重要问题就是如何做到让JavaScript既能与HTML页面共存,又不影响那些页面在其他浏览器中的呈现效果.经过尝试.纠错和争论,最终的决定就是为Web增加统一的脚本支持.而Web诞生早期的很多做法也都保留了下来,并被正式纳入HTML规范当中. <script&g

“全栈2019”Java第九十九章:局部内部类与继承详解

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第九十九章:局部内部类与继承详解 下一章 "全栈2019"Java第一百章:局部内部类可以实现接口吗? 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复"Java学习小

Android View 事件分发机制源码详解(View篇)

前言 在Android View 事件分发机制源码详解(ViewGroup篇)一文中,主要对ViewGroup#dispatchTouchEvent的源码做了相应的解析,其中说到在ViewGroup把事件传递给子View的时候,会调用子View的dispatchTouchEvent,这时分两种情况,如果子View也是一个ViewGroup那么再执行同样的流程继续把事件分发下去,即调用ViewGroup#dispatchTouchEvent:如果子View只是单纯的一个View,那么调用的是Vie