看了这个还分不清构造函数,实例对象,类,就来锤我

122 阅读4分钟
什么是构造函数

下面就是一个构造函数

//构造函数
function Student(name, age) {
    this.name = name;
    this.age = age;
    this.say=function (){}
}

// 根据构造函数 创建实例对象
var p1 = new Student("张三", 11);
var p2 = new Student("李四", 22);

构造函数的特点
  1. 构造函数的作用是专门用来创建某一类型的实例对象的 image.png
  2. 构造函数其实就是普通的函数,但是构造函数习惯上首字母大写
  3. 普通函数调用方式是直接调用的,构造函数需要使用 new 关键字来调用(构造函数的执行过程其实就是 new 的调用过程)
  4. 构造函数的函数名与类名相同,Student既是函数名,也是类名
  5. 构造函数会自动返回一个实例对象,普通函数没有写 return 则会返回 undefind
  6. 构造函数有原型对象 prototypeprototype 里面有 constructor,指向构造函数本身。 image.png
  7. 构造函数创建的实例对象有 __proto__ (没有prototype ), __proto__ 指向构造函数的原型对象 prototypeimage.png
构造函数的缺点

JS通过构造函数来生成实例对象,这样就会有一个问题,在构造函数中通过this赋值的属性或者方法,是每个实例自己的属性和方法,它是无法共享公共属性和方法的。

所以又设计出了一个原型对象(prototype),来存储这个构造函数的公共属性以及方法。这样就结局也了共享属性和方法的问题

//添加到到原型上的方法 会被所有实例对象共享
Student.prototype.show = function () {
    console.log("造化钟神秀");
}

所以这就是原型链设计的初衷

构造函数用来干什么

js比较熟悉的小伙伴肯定知道到 JS 一直到 ES6才有类(class)这个概念的,在es6之前,那JS的继承怎么来实现呢?

JS的设计者使用了构造函数来实现继承机制。而且ES6class其实只是一个语法糖,只是让写法更加清晰而已(继承后面再讲)

注意:
function Person(name, age) {
    this.name = name;
    this.age = age;
};
Person.ww = 'ww';
var p1 = new Person("aa", 11);
console.log( Person.ww); // ww
console.log( p1.ww); // undefined

添加 ww 属性的是 构造函数本身 ,而不是实例对象。

  • 类(class): 具备共同特征(属性和方法)事物的抽象,叫类

    例如: 人类、动物类、车类。。。。。一个大的分类

    ES6 引入了类的概念,这是一种更简洁、更易于阅读和理解的面向对象编程方式。类是一种特殊的函数,用于创建对象。

    es6 通过 class 关键字来定义一个类,与构造函数不同的是,类的定义中包含了构造函数以及其他方法和属性的定义。 class 关键字从语法上模拟了真正面向对象的语法。

  • 实例对象(object): 具体的一个实物,如: 李寻欢、大众辉腾、灰猫。。。。

      //父类
       class Person {
           //构造器  也就是构造函数
           constructor(name, age) {
               this.name = name;
               this.age = age;
           }
    
           // 原型方法  固定写法
           eat() {
               console.log('父类原型方法,吃!!!');
           }
    
       }
    
       // 子类
       class Student extends Person {
           // 构造函数(器)
           constructor(name, age, No) {
               super(name, age);  // 继承父类属性
               this.No = No; // 自己的属性
           }
           // 子类的原型方法
           study() {
               console.log('我爱学习!');
           }
       }
       // console.log(Person);
       var s1 = new Student("王五", 16, 22); // 实例对象
       var s2 = new Student("赵六", 18, 23);
       console.log('s1', s1);
       console.log('s2', s2);
       console.log('s1.study===s2.study', s1.study === s2.study); // true
       console.log('s1.eat===s2.eat', s1.eat === s2.eat); // true
       console.log(s1.study()); // 我爱学习!
       console.log(s1.eat());  // 父类原型方法,吃!!!
       console.log(s1 instanceof Student); // true
       console.log(s1 instanceof Person);  // true
       console.log(s1 instanceof Object);  // true
    
    
    constructor

    constructor 就相当于之前的构造函数了,负责初始化对象及接受参数。它是类的默认方法,通过 new 命令生成对象实例,自动调用该方法。一个类必须有 constructor 方法,如果没有显示定义,会被默认添加。

    // 定义了一个空的类Student,
       class Student {
           // JavaScript引擎会自动为它添加一个空的constructor方法
       }
    
       // 等同于
       // class Student {
       //     constructor() { }
       // }
    

    类既解决了构造函数的过载,又不再显式的通过原型对象去共享方法和属性。子类还可以通过 extends 关键字来 继承 父类

    为了实现继承,实例化时,传入参数首先被子类的 constructor 执行,但是,从语法上,应该时主类的 constructor 先执行,因此引入 super() 方法来调用主类的constructor

static

static 关键字, static 表示定义静态方法。不能在类的实例上调用静态方法,而应该通过类本身调用。

     class Person {
            //构造函数(构造器)  也就是构造函数
            constructor(name, age) {
                this.name = name;
                this.age = age;
            }

            // 原型方法  固定写法
            eat() {
                console.log('父类原型方法,吃!!!');
            }
            static game() {
                console.log('打高尔夫');
            }
            static run() {
                this.game();
                console.log('我跑的很快');
            }
        }
        var s1 = new Person("王五", 16, 22);
        console.log('Person.run()', Person.run()); //  打高尔夫   我跑的很快
        console.log('s1.eat()', s1.eat()); // 父类原型方法,吃!!
        console.log('s1.game()', s1.game()); //  undefined