JS 面向对象进阶

简介: JS 面向对象进阶

ES6简介:

     ES6 是 JavaScript 语言的下一代标准,全称ECMAScript 6.0,ECMAScript 是JavaScript语言的国际标准,JavaScript是ECMAScript的实现,ES6 使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。


一:走进面向对象

        学过编程语言例如C++,Java等等的小伙伴都或多或少接触到过面向对象 ,也都明白面向对象(OOP)和面向过程(POP)各自的优劣,下面卡卡西先带大家回顾一下二者各自的优劣


面向过程(POP):


优点:性能较面向对象而言更高,适用于与硬件联系紧密的操作,如单片机等

缺点:不易维护,不易拓展,不易复用

面向对象(OOP):


优点:由于面向对象有封装,继承,多态等特性,导致其更易维护,易拓展,易复用

缺点:性能相较于面向过程低

面向对象的思维特点:


面向对象的思维特点就是:抽取事物的公共属性公共方法封装成一个类,然后对类进行实例化,例如我们生产手机,我们先将手机公共的属性方法例如打电话,发短信封装为一个类,在实际生产时我们只需要实例化生成手机即可

      总而言之,我们可以这样理解面向对象与面向过程,面向过程是一份鸡汤排骨面,而面向对象是一份清汤面,想让其成为鸡汤排骨面就放入鸡汤排骨,想让其称为番茄面就放入番茄,,是不是更好理解了呢?




二:类和对象

     在 Java Script 中,万物皆为对象,对象是一组相关属性和方法的集合,一个字符串,一个数组......万物皆为对象


对象有如下特点:


对象由一系列属性和方法构成

对象的属性即对象拥有的特征,专用名词为属性

对象的方法即对象拥有的行为,专用名词为方法



类有如下特点:


类是ES6中新增的概念,可以使用class声明类,再用该类实例化对象


类抽象了对象的公共部分,例如手机都有打电话发短信功能,那我们就可以创建一个类,里面的方法为打电话发短信,我们生产手机时生产哪个牌子的就用该类实例化一个对象即可

对象是特指的某一个对象,而类是泛指的

三:创建类与生成实例

此版块我们学习创建类与对象的实例化


基本书写格式:(此处举例类名为 Animal)


//创建类


class Animal {


      ........


}


//实例化对象dog


var dog=new Animal()


<script>

//创建类

     class Animal{

          //填充内容

     }

//实例化对象

     var dog=new Animal();

</script>

注意点:

类名最好首字母大写!!

类名后直接跟花括号,不需要加小括号

实例化对象必须使用关键字new

实例化对象要加小括号

要先有了类,才能对象实例化,因为在es6中没有变量提升

四:constructor 构造函数

      constructor 是类的默认构造函数,用于传参并返回给实例对象,在使用new生成实例对象时自动调用该方法,如果没有在类中明确写出该方法,则系统也会默认创建一个该方法


基本书写格式:(以参数为uname为例)


constructor (uname){


       this.uname=uname;


}


<script>

     class Animal{

          constructor(uname){

              this.uname=uname;

          }

     }

     var dog=new Animal('旺财');

     console.log(dog.uname);

</script>



传参过程:


第一步:在 new 实例化对象时就会调用 constructor 构造函数,并把参数 '旺财' 传递给构造函数的参数 uname

第二步:于是 uname 就把旺财传递给了 this.uname

第三步:this 指向的就是创建好的实例化对象,于是对象 dog 就有了 uname=旺财

注意点:

类内的方法不需要加 function

类内的共有属性和方法的使用一定要在前面加 this(非常非常非常重要)

五:类中添加共有方法

类中不止只会有constructor构造函数,还会有普通的共有方法


基本书写格式:


eat( ){


         ......


}


<script>

     class Animal{

          constructor(uname){

              this.uname=uname;

          }

          eat(food){

              console.log(this.uname + '在吃' + food);

          }

     }

     var dog=new Animal('旺财');

     var cat=new Animal('咪咪');

     dog.eat('骨头');

     cat.eat('鲤鱼');

</script>



注意点:

可以有参可以无参

类中的多个方法之间不需要逗号分隔

类中的方法不需要加 function

六:类继承 extends

     面向对象三大特点:封装,继承,多态,这里我们讲解继承,继承顾名思义,就是一个子类可以调用父类中的内容


继承书写格式:(此处举例子类继承父类)


class Son extends Father{


        ......


}


<script>

     class Father{

         constructor(){ }

         say(){

             console.log('hello');

         }

     }

     class Son extends Father{

     }

     var son1=new Son();

     son1.say();

</script>



对于有传参情况的,可能需要用到super关键字,下一个内容将讲到


七:super关键字

super() 作为函数调用时就代表父类的构造函数,ES6要求子类构造函数必须执行super()


7.1 构造函数内的 super 使用

在开始讲解super前我们先看一个报错案例:


例如我们要调用父类的加法函数,但是在子类实例化传参


<script>

     class Father{

         constructor(x,y){

             this.x=x;

             this.y=y;

         }

         sum(){

             console.log(this.x+this.y);

         }

     }

     class Son extends Father{

         constructor(x,y){

             this.x=x;

             this.y=y;

         }

     }

     var son1=new Son(1,5);

     son1.sum();

</script>




报错原因分析:


第一步:我们实例化了对象son1,new的同时会调用son类的构造函数,并把参数1和5传递给子类的构造函数中,子类构造函数中的this指向对象son1

第二步:而对象son1调用父类sum函数时,sum中的this.x与this.x指向的是父类的构造函数中的值,所以会报错

2. 使用 super关键字 更正错误


只需要将子类构造函数内加入super()关键字并传参进去即可,实际内部产生了以下步骤:


第一步:实例化传参给子类构造函数,构造函数内的函数会自动调用,于是调用了super方法

第二步:子类构造函数内的值传递给了super(),super实际上为调用父类构造函数,于是参数传递给了父类构造函数

第三步:父类sum方法的this指向的是父类构造函数内的值,而此时已经通过super传入了值,故不会再报错

<script>

     class Father{

         constructor(x,y){

             this.x=x;

             this.y=y;

         }

         sum(){

             console.log(this.x+this.y);

         }

     }

     class Son extends Father{

         constructor(x,y){

             super(x,y)

         }

     }

     var son1=new Son(1,5);

     son1.sum();

</script>





构造函数内使用super注意点:

super 必须放在子类的 this 之前

7.2 super 调用父类的普通方法

       在继承中调用普通方法,我们要记住一个 就近原则 ,那就是在继承中调用一个方法时,要先看子类自身有没有该方法,如果子类自身有而父类没有,就调用子类自身的,如果子类自身没有而父类有,就调用父类,如果都有,就会默认调用子类的,父类的则可以使用super调用


格式:super . 方法

下面我们举例继承中父子同名的方法的调用:

<script>

     class Father{

          constructor(){

          }

          say(){

               return '我是爸爸';

          }

     }

     class Son extends Father{

          say(){

              console.log(super.say()+'的儿子');

          }

     }

     var son1=new Son(1,5);

     son1.say();

</script>




这样就做到了即调用了父类的也调用了子类的同名方法


八:类中 this 的指向

类中的this指向问题:


constructor 中的 this 指向的是创建的实例对象

类的方法中的 this 指向的是方法的调用者

那如果我们在类方法中需要用到构造函数中的 this 指向怎么办?

例如这种情况:


<body>

   <button>开始吃</button>

<script>

     class Animal{

          constructor(uname){

              this.uname=uname;

              this.btn=document.querySelector('button');

              this.btn.addEventListener('click',this.eat)

          }

          eat(){

              console.log(this.uname + '正在吃骨头');

          }

     }

     var dog=new Animal('旺财');

</script>

</body>




    我们按下按钮后得到了 undefined,这是因为,由于是按钮调用了类内的方法 eat,所以 eat内的 this 指向的是这个按钮 btn,而不是实例化对象,由于按钮 btn 没有 uname 属性,所以输出了 undefined


解决方案:

      由于我们需要得到指向实例化对象的 this,所以我们需要得到构造函数内的 this,故而只需要将构造函数内的  this 赋值给一个变量,在类方法内调用时不再用 this 指明,而用赋值了指向实例化对象的变量即可解决


<body>

   <button>开始吃</button>

<script>

   var flag;  //声明一个变量去存放

     class Animal{

          constructor(uname){

              flag=this;   //将指向实例化对象的this赋值

              this.uname=uname;

              this.btn=document.querySelector('button');

              this.btn.addEventListener('click',this.eat)

          }

          eat(){

              console.log(flag.uname + '正在吃骨头');  //此处使用赋值了指向实例化对象的flag去指即可

          }

     }

     var dog=new Animal('旺财');

</script>

</body>




问题解决!



相关文章
|
6月前
|
前端开发 JavaScript 开发者
JavaScript进阶-Promise与异步编程
【6月更文挑战第20天】JavaScript的Promise简化了异步操作,从ES6开始成为标准。Promise有三种状态:pending、fulfilled和rejected。基本用法涉及构造函数和`.then`处理结果,如: ```javascript new Promise((resolve, reject) =&gt; { setTimeout(resolve, 2000, &#39;成功&#39;); }).then(console.log); // 输出: 成功
91 4
|
6月前
|
存储 JavaScript 前端开发
JavaScript进阶-Map与Set集合
【6月更文挑战第20天】JavaScript的ES6引入了`Map`和`Set`,它们是高效处理集合数据的工具。`Map`允许任何类型的键,提供唯一键值对;`Set`存储唯一值。使用`Map`时,注意键可以非字符串,用`has`检查键存在。`Set`常用于数组去重,如`[...new Set(array)]`。了解它们的高级应用,如结构转换和高效查询,能提升代码质量。别忘了`WeakMap`用于弱引用键,防止内存泄漏。实践使用以加深理解。
83 3
|
5月前
|
XML 前端开发 JavaScript
JavaScript进阶 - AJAX请求与Fetch API
【7月更文挑战第3天】前端开发中的异步基石:AJAX与Fetch。AJAX,使用XMLHttpRequest,处理跨域、回调地狱和错误处理。Fetch,基于Promise,简化请求,但需注意默认无跨域头和HTTP错误处理。两者各有优劣,理解其问题与解决策略,能提升前端应用的性能和用户体验。
158 24
|
6月前
|
设计模式 JavaScript 前端开发
【JavaScript】深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略
JavaScript的继承机制基于原型链,它定义了对象属性和方法的查找规则。每个对象都有一个原型,通过原型链,对象能访问到构造函数原型上的方法。例如`Animal.prototype`上的`speak`方法可被`Animal`实例访问。原型链的尽头是`Object.prototype`,其`[[Prototype]]`为`null`。继承方式包括原型链继承(通过`Object.create`)、构造函数继承(使用`call`或`apply`)和组合继承(结合两者)。ES6的`class`语法是语法糖,但底层仍基于原型。继承选择应根据需求,理解原型链原理对JavaScript面向对象编程至关重要
146 7
【JavaScript】深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略
|
5月前
|
前端开发 JavaScript 安全
JavaScript进阶-JavaScript库与框架简介
【7月更文挑战第11天】JavaScript库和框架加速Web开发,但也带来挑战。选择适合项目、团队技能的库或框架,如React、Angular、Vue,是关键。保持依赖更新,注意性能优化,避免过度依赖。遵循最佳实践,确保安全性,如防XSS和CSRF。学习基础,结合代码示例(如React计数器组件),提升开发效率和应用质量。
64 1
|
5月前
|
缓存 JavaScript 前端开发
JavaScript进阶 - Web Workers与Service Worker
【7月更文挑战第4天】JavaScript的Web Workers和Service Worker增强了Web性能。Web Workers处理后台多线程,减轻主线程负担,但通信有开销,受同源策略限制。Service Worker则用于离线缓存和推送通知,需管理其生命周期、更新策略,并确保安全。两者都带来了挑战,但也极大提升了用户体验。通过理解和优化,开发者能构建更高效、安全的Web应用。
138 2
|
5月前
|
资源调度 JavaScript 前端开发
JavaScript进阶 - JavaScript库与框架简介
【7月更文挑战第5天】JavaScript库和框架构成了前端开发的核心,如jQuery简化DOM操作,Angular、React和Vue提供全面解决方案。选择时要明确需求,避免过度工程化和陡峭学习曲线。使用版本管理工具确保兼容性,持续学习以适应技术变化。示例展示了jQuery和React的简单应用。正确选择和使用这些工具,能提升开发效率并创造优秀Web应用。
52 2
|
5月前
|
设计模式 前端开发 JavaScript
JavaScript进阶 - JavaScript设计模式
【7月更文挑战第1天】JavaScript设计模式增进代码复用和维护性。单例模式确保唯一实例,用闭包防止命名冲突和控制状态访问。观察者模式实现一对多依赖,通过解绑避免内存泄漏。工厂模式封装对象创建,适度使用避免复杂度。装饰者模式动态添加行为,保持简洁以保可读性。理解模式的优缺点,灵活应用,提升代码质量。
131 3
|
5月前
|
存储 前端开发 安全
JavaScript进阶 - 浏览器存储:localStorage, sessionStorage, cookies
【7月更文挑战第2天】探索Web存储:localStorage持久化,sessionStorage会话限定,cookies则伴随HTTP请求。了解它们的特性和限制,如localStorage的5MB容量限制、跨域问题,sessionStorage的生命周期,及cookies的安全与带宽消耗。使用时需权衡安全、效率与应用场景。示例代码展示存储与检索方法。
338 2
|
6月前
|
JavaScript 前端开发
JavaScript进阶-Class与模块化编程
【6月更文挑战第21天】**ES6引入Class和模块化,提升JavaScript的代码组织和复用。Class是原型机制的语法糖,简化面向对象编程。模块化通过`import/export`管理代码,支持默认和命名导出。常见问题包括`this`指向和循环依赖。理解这些问题及避免策略,能助你写出更高效、可维护的代码。**
66 5