js面向对象class类 construct 继承中的extends super

JavaScript面向对象开发常见问题


此文章适合还未接触过大型项目开发和准备步入职场的小白


一、 什么是面向对象


    刚学习js就听说过万物皆对象,在实际工作中确实如此,项目中把需要的每一个需求或者一个部分,封装成一个类,从而提升代码的可复用性和维护性。
    在实际工作中面向对象开发模式非常常见,可以理解为类似装修,封装了一个家具类、电器类等等




二、对象的创建方式


1、构造函数


    在学校里老师都会教一个叫构造函数的东西,并且一般都是这样书写的:

 function Person(name, age) {
   this.name = name;
   this.age = age;
   this.print= function() {
     console.log('姓名:' + this.name + '  ' + '年龄:' + this.age );
   }
 }

//相应的创建方式
var person1 = new Person("孙悟空",18)

首先构造函数也是一种函数,并没有什么特别之处



2、ES6 class创建


    在学校几乎没有太接触过class这个概念,在网上了解过一些,具体概念这里不再陈述,直接说一些简单的例子,下面class的写法等同上面构造函数的效果

class Person {
      constructor(name, age) {
        this.name = name;
        this.age = age;
      }
      print = function(){
        console.log('姓名:' + this.name + '  ' + '年龄:' + this.age );
      }
    }

   var person1 = new Person("孙悟空", 18)

    不知道看到这里你是否有些疑惑。我在学习的时候我就产生了一个疑惑,上一部分构造函数结构分明,但是ES6中class中多了许多东西,construct是什么?为什么属性写在了construct里,而方法写在了外部?为什么属性前有this而方法并没有?




三、构造函数与class


    首先我们先来看构造函数。构造函数在声明的时候,为什么要做this.name = name,this.age = age?

在这里插入图片描述

1、首先this粗略来说,指向创建的实例对象,也就是这里的person1;
2、this.name、this.age表明实例对象上有两个属性:一个叫name,一个叫age,还有一个方法叫:print;
3、实例对象上这两个属性值,在构造函数里并没有写死,具体值由创建实例对象的时候实参决定。


    由此构造函数,我们可以创建不同的“Person”实例对象,我们甚至可以创建师徒四人出来

	//接收两个参数
    function Person(name, age) {
      this.name = name;
      this.age = age;
      this.print = function () {
        console.log('姓名:' + this.name + '  ' + '年龄:' + this.age);
      }
    }
	//实例化时传参
    var person1 = new Person("孙悟空", 18);
    var person2 = new Person("唐僧", 35);
    var person3 = new Person("猪八戒", 40);
    var person4 = new Person("沙和尚", 55);

在这里插入图片描述

    而如果我不需要不同的对象,我只想要孙悟空,我想要很多个“孙悟空”,我这里压根就不需要传值

//不需要形参接收参数
function Person() {
      this.name = "孙悟空";
      this.age = 18;
      this.print = function () {
        console.log('姓名:' + this.name + '  ' + '年龄:' + this.age);
      }
    }
	//实例化时不需要传参
    var person1 = new Person();
    var person2 = new Person();
    var person3 = new Person();
    var person4 = new Person();

在这里插入图片描述

说这些很简单,接下来我们来看class

class Person {
      constructor(name, age) {
        this.name = name;
        this.age = age;
      }
      print = function(){
        console.log('姓名:' + this.name + '  ' + '年龄:' + this.age );
      }
    }

   var person1 = new Person("孙悟空", 18)

    还是上面给过的一模一样的代码,通过这个class类,我们也可以创建很多个实例,只需要在new的时候传不同的参数即可

如果这里我不需要灵活创建对象呢?我就需要很多个孙悟空


代码如下:

class Person{
      name = "孙悟空"
      age = 18
      print(){
        console.log('姓名:' + this.name + '  ' + '年龄:' + this.age);
      }
    }

    var person1 = new Person();
    var person2 = new Person();
    var person3 = new Person();
    var person4 = new Person();

    和构造函数一样,不用接收参数了。但是特殊的是:construct不见了,this也不见了




四、construct有什么用


定义: constructor 是类的构造函数,他是方法,在new实例化的时候,会自动调用这个函数,这一句话就可以解决刚刚的问题


1、首先construct在实例化对象的时候,会自动调用,如果需要传递参数,可以在construct中接收
在这里插入图片描述

2、construct是实例化对象的一个方法,它是一个函数。如果在其中定义的属性不加上this,是会报错的。原因是:this永远指向调用此函数的人,这里实例化对象的时候谁在调用construct?就是那个对象,所以给这个对象添加属性或方法时,需要加上this
在这里插入图片描述

3、construct在实例化对象时会自动调用,所以可以在其中调用函数

     class Person {
      constructor(name, age) {
        this.name = name;
        this.age = age;
        // 在constru中调用对象的print方法
        this.print()
      }
      print(){
        console.log("我是" + this.name);
      }
    }

    var person1 = new Person("孙悟空", 18)

控制台输出:
在这里插入图片描述

    注意,我这里只new了一个对象,并没有打印输出任何东西。之所以控制台打印了信息,是因为这里在实例化对象的时候自动会调用construct,而在construct中调用了print方法


简单总结:
1、construct会在实例化对象的时候调用,他是个函数,所以在其中定义属性或者方法要写this;

2、需要接收参数可以在construct中接收;
3、construct会被立刻调用,需要调用的方法也可以写在其中。





五、extends、super


    除了构造函数和class,在面向对象编程中还会遇到继承的问题

    继承可以理解为,一个类去继承另一个类,子类可以获取到父类的属性和方法。在子类中如果要使用construct,必须要调用super(),因为子类本身并没有自己的this对象,他必须从父类继承;如果不使用construct,会自动调用父类的construct

    //父类
    class Person {
      constructor(name, age) {
        this.name = name;
        this.age = age
      }
      print() {
        console.log('我是父类的print' + '姓名:' + this.name + '  ' + '年龄:' + this.age)
      }
    }
    //子类
    class Man extends Person {
      constructor(name, age) {
        super(name, age)
      }
      print() {
        super.print();
        console.log('我是子类的print' + '姓名:' + this.name + '  ' + '年龄:' + this.age)
      }
    }

    let person1 = new Man("孙悟空", 18)
    console.log(person1.name, person1.age)
    person1.print()

上述代码出现了两次super

第一次super作为函数调用,此处可以理解为父类的构造函数,这里实际上原理是改变了this指向问题,Person.prototype.constructor.call(this, props)


第二次super作为对象来使用,指向父类的原型对象,这里其实动作是 super.print.call(this)




六、总结

    在面向对象的开发中,这些都是很基础的,如何使用class创建,construct是什么?怎么用?extends继承和super的使用原理,这些最基础的都需要掌握。

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值