广告
返回顶部
首页 > 资讯 > 前端开发 > html >JavaScript的面向对象和它的封装、继承、多态简单介绍
  • 910
分享到

JavaScript的面向对象和它的封装、继承、多态简单介绍

2024-04-02 19:04:59 910人浏览 薄情痞子
摘要

这篇文章主要介绍“javascript的面向对象和它的封装、继承、多态简单介绍”,在日常操作中,相信很多人在JavaScript的面向对象和它的封装、继承、多态简单介绍问题上存在疑惑,小编查阅了各式资料,整

这篇文章主要介绍“javascript面向对象和它的封装、继承、多态简单介绍”,在日常操作中,相信很多人在JavaScript的面向对象和它的封装、继承、多态简单介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JavaScript的面向对象和它的封装、继承、多态简单介绍”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

面向对象与面向过程

面向对象和面向过程是两种不同的编程思想,刚开始接触编程的时候,我们大都是从面向过程起步的,毕竟像我一样,大家接触的***门计算机语言大概率都是C语言,C语言就是一门典型的面向过程的计算机语言。

面向过程主要是以动词为主,解决问题的方式是按照顺序一步一步调用不同的函数。

面向对象是以名词为主,将问题抽象出具体的对象,而这个对象有自己的属性和方法,在解决问题的时候,是将不同的对象组合在一起使用。

//面向过程装大象  1.开(冰箱)  2.(大象)装进(冰箱)  3.关(冰箱)
//面向对象装大象  1. 冰箱.开门()  2. 冰箱.装进(大象)  3. 冰箱.关门()

从这个例子可以看出,面向对象是以主谓为主,将主谓堪称一个一个的对象,然后对象有自己的属性和方法。

面向对象是以功能来划分问题的,而不是步骤。功能上的统一保证了面向对象设计的可扩展性,解决了代码重用性的问题。

这也是在漫长的程序设计的发展过程中得到的验证结果,面向对象的编程思想较之于面向过程较好一点

封装

面向对象有封装、继承和多态三大特性。

封装:就是把事物封装成类,隐藏事物的属性和方法的实现细节,仅对外公开接口。

在ES5中,并没有class的概念,但是由于js的函数级作用域(函数内部的变量函数外访问不到)。所以我们可以模拟class。在es5中,类其实就是保存了一个函数的变量,这个函数有自己的属性和方法。将属性和方法组成一个类的过程就是封装。

1.通过构造函数添加

JavaScript提供了一个构造函数(Constructor)模式,用来在创建对象时初始化对象。构造函数其实就是普通的函数,只不过有以下的特点

①首字母大写(建议构造函数首字母大写,即使用大驼峰命名,非构造函数首字母小写)  ②内部使用this  ③使用new生成实例

通过构造函数添加属性和方法实际上也就是通过this添加的属性和方法。因为this总是指向当前对象的,所以通过this添加的属性和方法只在当前对象上添加,是该对象自身拥有的。所以我们实例化一个新对象的时候,this指向的属性和方法都会得到相应的创建,也就是会在内存中复制一份,这样就造成了内存的浪费。

function Cat(name,color){      this.name = name;      this.color = color;      this.eat = (() => {          console.log("fish!")      })  }  //生成实例  var cat1 = new Cat("tom", "gray")

通过this定义的属性和方法,我们实例化对象的时候斗湖重新复制一份

2.通过原型prototype封装

在类上通过this的方式添加属性和方法会导致内存浪费的现象,有什么办法可以让实例化的类所使用的属性和方法 直接使用指针 指向同一个属性和方法。

这就是原型的方法

JavaScript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。  也就是说,对于那些不变的属性和方法,我们可以直接将其添加在类的prototype对象上。
function Cat(name,color){              this.name = name;              this.color = color;          }          Cat.prototype.type = "英短";          Cat.prototype.eat = ( () => {              alert("fish!")          } )                //生成实例          var cat1 = new Cat('Tom', 'gray');          var cat2 = new Cat('Kobe', 'purple');          console.log(cat1.type); //英短          cat2.eat(); //fish!

这时所有实例的type属性和eat()方法,其实都是同一个内存地址,指向prototype对象,因此就提高了运行效率。

但是这样做也有弊端,因为实例化的对象的原型都是指向同一内存地址,改动其中一个对象的属性可能会影响到其他的对象

es6中的类和封装

es6声明一个类

①构造器:构造器内创建自有属性

②方法:声明类实例具有的方法

class Cat {      //等价于Cat构造器      constructor(name) {          this.name = name;      }      //更加简单的声明类的内部函数      //等价于 Cat.prototype.eat      eat() {          console.log("fish!");      }  }  //生成实例  var cat1 = new Cat("tom");  cat1.eat(); //fish!  console.log(cat1 instanceof Cat); //true  console.log(cat1 instanceof Object); //true  console.log(typeof Cat); //function  console.log(typeof Cat.prototype.eat); //function

从上面class声明的Cat为例:Cat类是一个具有构造函数行为的函数,其中内部方法eat实际上就是Cat.prototype.eat()

所以说es6的class封装类,本质上是es5实现方式的语法糖

最主要的区别在于,class类的属性是不可重新赋值和不可枚举的,Cat.prototype就是一个只读属性

class和自定义类型的区别

(1)class的声明不会提升,与let类似

(2)class的声明自动运行于严格模式之下

(3)class声明的方法不可枚举

(4)class的内部方法没有 constructor 属性,无法new

(5)调用class的构造函数必须new

(6)class内部方法不能同名

class类的使用

class作为js中的一级公民,可以被当作值来直接使用

//1.类名作为参数传入函数  function createObj (ClassName) {      return new ClassName()  }  //2.立即执行,实现单例模式  let cat1 = new class{      constructor (name) {          this.name = name      }      eat() {          console.log("fish!")      }  }("tom”)  cat1.eat() //fish!

继承

继承就是子类可以使用父类的所有功能,并且对这些功能进行扩展。继承的过程,就是从一般到特殊的过程。

1.类式继承

所谓的类式继承就是使用的原型的方式,将方法添加在父类的原型上,然后子类的原型是父类的一个实例化对象。

//声明父类  var SuperClass = function(){      let id = 1;      this.name = ['java'];      this.superValue = function() {          console.log('this is superValue!')      } }  //为父类添加共有方法  SuperClass.prototype.getSuperValue = function () {      return this.superValue();  };  //声明子类  var SubClass = function() {      this.subValue = (() => {          console.log('this is subValue!')      })  }  //继承父类  SubClass.prototype = new SuperClass();  //为子类添加共有方法  SubClass.prototype.getSubValue = function() {      return this.subValue()  }  //生成实例  var sub1 = new SubClass();  var sub2 = new SubClass();  sub1.getSuperValue(); //this is superValue!  sub1.getSubValue(); //this is subValue!  console.log(sub1.id); //undefined  console.log(sub1.name); //["java"]  sub1.name.push("PHP");   console.log(sub1.name); //["java", "php"]  console.log(sub2.name); //["java", "php"]

其中最核心的是SubClass.prototype = new SuperClass();

类的原型对象prototype对象的作用就是为类的原型添加共有的方法的,但是类不能直接访问这些方法,只有将类实例化之后,新创建的对象复制了父类构造函数的属性和方法,并将原型 proto 指向了父类的原型对象。这样子类就可以访问父类的属性和方法,同时,父类中定义的属性和方法不会被子类继承。

but使用类继承的方法,如果父类的构造函数中有引用数据类型,就会在子类中被所有实例共用,因此一个子类的实例如果更改了这个引用数据类型,就会影响到其他子类的实例。

构造函数继承

为了克服类继承的缺点,才有了构造函数继承,构造函数继承的核心思想就是SuperClass.call(this, id),直接改变this的指向,使通过this创建的属性和方法在子类中复制一份,因为是单独复制的,所以各个实例化的子类互不影响。but会造成内存浪费的问题

//构造函数继承  //声明父类  var SuperClass = function(id){      var name = 'java'      this.languages = ['java', 'php', 'ruby'];      this.id = id   }  //声明子类  var SubClass = function(id){      SuperClass.call(this, id)  }  //生成实例  var sub1 = new SubClass(1);  var sub2 = new SubClass(2);  console.log(sub2.id); // 2  console.log(sub1.name); //undefined  sub1.languages.push("python");  console.log(sub1.languages); // ['java', 'php', 'ruby', 'Python']  console.log(sub2.languages); // ['java', 'php', 'ruby']

组合式继承

组合式继承是汲取了两者的优点,既避免了内存浪费,又使得每个实例化的子类互不影响。

//组合式继承  //声明父类  var SuperClass = function(name){      this.languages = ['java', 'php', 'ruby'];      this.name = name;  }   //声明父类原型方法  SuperClass.prototype.showLangs = function () {      console.log(this.languages);  }  //声明子类  var SubClass = function(name){      SuperClass.call(this, name)  }  //子类继承父类(链式继承)  SubClass.prototype = new SuperClass();  //生成实例  var sub1 = new SubClass('python');  var sub2 = new SubClass('Go');  sub2.showLangs(); //['java', 'php', 'ruby']  sub1.languages.push(sub1.name);  console.log(sub1.languages);//["java", "php", "ruby", "python"]  console.log(sub2.languages);//['java', 'php', 'ruby']

but警告:组合式继承方法固然好,但是会导致一个问题,父类的构造函数会被创建两次(call()的时候一遍,new的时候又一遍)

寄生组合继承

组合式继承的缺点的关键是 父类的构造函数在类继承和构造函数继承的组合形式被创建了两边,但是在类继承中我们并不需要创建父类的构造函数,我们只要子类继承父类的原型即可。

所以我们先给父类的原型创建一个副本,然后修改子类的 constructor 属性,***在设置子类的原型就可以了

//原型式继承  //原型式继承其实就是类式继承的封装,实现的功能返回一个实例,该实例的原型继承了传入的o对象  function inheritObject(o) {      //声明一个过渡函数      function F() {}      //过渡对象的原型链继承父对象      F.prototype = o;      //返回一个过渡对象的实例,该实例的原型继承了父对象      return new F();  }  //寄生式继承  //寄生式继承就是对原型继承的第二次封装,使得子类的原型等于父类的原型。并且在第二次封装的过程中对继承的对象进行了扩展  function inheritPrototype(subClass, superClass){      //复制一份父类的原型保存在变量中,使得p的原型等于父类的原型      var p = inheritObject(superClass.prototype);      //修正因为重写子类原型导致子类constructor属性被修改      p.constructor = subClass;      //设置子类的原型      subClass.prototype = p;  }  //定义父类  var SuperClass = function(name) {      this.name = name;      this.languages = ["java", "php", "python"]  }  //定义父类原型方法  SuperClass.prototype.showLangs = function() {      console.log(this.languages);  }  //定义子类  var SubClass = function(name) {      SuperClass.call(this,name)  }  inheritPrototype(SubClass, SuperClass);  var sub1 = new SubClass('go');

es6中的继承

class SuperClass {      constructor(name) {          this.name = name          this.languages = ['java', 'php', 'go'];       }      showLangs() {          console.log(this.languages);      }  }  class SubClass extends SuperClass {      constructor(name) {          super(name)      }      //重写父类中的方法      showLangs() {          this.languages.push(this.name)          console.log(this.languages);      }  }  //生成实例  var sub = new SubClass('韩二虎');  console.log(sub.name); //韩二虎  sub.showLangs(); //["java", "php", "go", "韩二虎"]

多态

多态实际上是不同对象作用与同一操作产生不同的效果。多态的思想实际上是把 “想做什么” 和 “谁去做” 分开。

多态的好处在于,你不必再向对象询问“你是什么类型”后根据得到的答案再去调用对象的某个行为。你尽管去调用这个行为就是了,其他的一切可以由多态来负责。规范来说,多态最根本的作用就是通过吧过程化的条件语句转化为对象的多态性,从而消除这些条件分支语句。

由于JavaScript中提到的关于多态的详细介绍并不多,这里简单的通过一个例子来介绍就好

//非多态       var hobby = function(animal){      if(animal == 'cat'){          cat.eat()      }else if(animal == 'dog'){          dog.eat()      }  }  var cat = {      eat: function() {          alert("fish!")      }  }  var dog = {      eat: function() {          alert("meat!")      }  }  console.log(123);  hobby('cat'); //fish!  hobby('dog'); //meat!

从上面的例子能看到,虽然 hobby 函数目前保持了一定的弹性,但这种弹性很脆弱的,一旦需要替换或者增加成其他的animal,必须改动hobby函数,继续往里面堆砌条件分支语句。我们把程序中相同的部分抽象出来,那就是吃某个东西。然后再重新编程。

//多态       var hobby = function(animal){      if(animal.eat instanceof Function){          animal.eat();      }  }  var cat = {      eat: function() {          alert("fish!")      }  }  var dog = {      eat: function() {          alert("meat!")      } }

现在来看这段代码中的多态性。当我们向两种 animal 发出 eat 的消息时,会分别调用他们的 eat 方法,就会产生不同的执行结果。对象的多态性提示我们,“做什么” 和 “怎么去做”是可以分开的,这样代码的弹性就增强了很多。即使以后增加了其他的animal,hobby函数仍旧不会做任何改变。

//多态       var hobby = function(animal){      if(animal.eat instanceof Function){          animal.eat();      }  }  var cat = {      eat: function() {          alert("fish!")      }  }  var dog = {      eat: function() {          alert("meat!")      }  }  var aoteman = {      eat: function(){          alert("lil-monster!")      }  }  hobby(cat); //fish!  hobby(dog); //meat!  hobby(aoteman); //lil-monster!

到此,关于“JavaScript的面向对象和它的封装、继承、多态简单介绍”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: JavaScript的面向对象和它的封装、继承、多态简单介绍

本文链接: https://www.lsjlt.com/news/81102.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JavaScript的面向对象和它的封装、继承、多态简单介绍
    这篇文章主要介绍“JavaScript的面向对象和它的封装、继承、多态简单介绍”,在日常操作中,相信很多人在JavaScript的面向对象和它的封装、继承、多态简单介绍问题上存在疑惑,小编查阅了各式资料,整...
    99+
    2022-10-19
  • Python面向对象封装继承和多态示例讲解
    目录1. 封装2. 继承多态的实现面向对象的三大特征:封装,继承,多态 1.封装: 提高程序的安全性 将数据(属性)和行为(方法)包装到类对象中,在方法内部对属性进行对象的...
    99+
    2022-11-12
  • Python面向对象的三大特性封装、继承、多态
    Python是一门面向对象的语言。面向对象都有三大特性:封装、继承、多态。 下面分别来说说这三大特性: 1、封装 隐藏对象的属性和实现细节,仅对外提供公共访问方式。在python中用...
    99+
    2022-11-11
  • Python的类、继承和多态简单介绍
    这篇文章主要讲解了“Python的类、继承和多态简单介绍”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python的类、继承和多态简单介绍”吧!类的定义假如要定义一个类 Point,表示二维...
    99+
    2023-06-17
  • 详细理解JAVA面向对象的封装,继承,多态,抽象
    目录类和对象的使用(面向对象思想落地的实现):子类对象实例化的全过程1.从结果上看:(继承性)2.从过程上来看:1.封装性2.继承性继承性的好处:3.多态性虚拟方法调用4.抽象性1....
    99+
    2022-11-12
  • Java面向对象基础知识之封装,继承,多态和抽象
    目录一、封装二、继承三、多态四、抽象总结一、封装 封装:是面向对象方法的重要原则,就是把对象的属性和行为(数据)结合为一个独立的整体,并尽可能隐藏对象的内部实现细节,就是把不想告诉或...
    99+
    2022-11-12
  • JavaScript面向对象中的封装和继承你了解吗
    目录1、面向对象1、封装2、原型对象3、继承总结1、面向对象 【三大显著特征】: 封装、继承、多态 1、封装 【解释】: 封装的本质就是将有关联的代码组合在一起。...
    99+
    2022-11-13
  • JavaScript面向对象中的封装和继承怎么实现
    这篇“JavaScript面向对象中的封装和继承怎么实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“JavaScript面...
    99+
    2023-06-29
  • 什么是面向对象,它的三个基本特征:封装、继承、多态
    什么是面向对象思想?已经学完了java确不知道如何跟别人解释面向对象是什么意思这很常见。让我们一起来回顾下这个奇思妙想~ 文章目录 一、面向对象与面向过程1、什么是面向过程?2、什么是面向对象? 二、类与对象的关系1、基本概念2...
    99+
    2023-08-16
    面向对象编程 java 封装 继承 多态
  • Java轻松掌握面向对象的三大特性封装与继承和多态
    目录1.封装1.介绍2.封装的理解和好处3.封装的实现步骤2.继承1.介绍2.继承的基本语法3.继承的使用细节3.super关键字1.基本介绍2.基本语法3.细节与好处4.super...
    99+
    2022-11-13
  • 深入浅析java中面向对象的继承和多态
    深入浅析java中面向对象的继承和多态?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。继承和多态一.this super关键字this: 可以在构造器中的第一代码中...
    99+
    2023-05-31
    java 继承 多态
  • 【Java面向对象】多态的详细介绍,简单易懂,看这一篇就够了
    文章目录 什么是多态多态的优点多态的分类重载式多态案例 重写式多态 多态的向上转型案例 多态的向下转型案例 什么是多态 A: 方法或对象具有多种形态,是面向对象的第三...
    99+
    2023-10-07
    java 数据结构 javascript jvm
  • Java面向对象编程之继承和多态以及包的解析与使用范例
    目录1.继承1.1继承的基本使用1.2 protected 关键字1.3 final 关键字2.多态2.1向上转型2.2动态绑定2.3方法重写2.4向下转型2.5super 关键字2...
    99+
    2022-11-12
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作