构造函数

关于函数的调用有很多种,比如直接圆括号执行,数组或者对象枚举执行,定时器调用,DOM事件处理函数调用。随着调用函数方式不同, 所以函数上下文也就不同

还有另外这一种调用函数的方式,使用new 关键字调用

比如下面的代码

 function fun() {
        console.log("hello");
      }
      new fun();

new 关键字调用函数会发生下面四步走

1> 函数里面会秘密创建一个新的空对象

2> this上下文指向这个新创建的空对象

3> 执行函数中所有的语句

4> 返回这个新对象

 

比如下面的代码

    function Person(name, age, sex) {
        this.name = name;
        this.age = age;
        console.log(this,'this')
      }
      var xiaoming = new Person("小明", 18);
      console.log(xiaoming,'xiaoming');

 

 

 

 new关键字创建的函数就叫做构造函数

new出来的结果就是构造函数的实例

 

构造有什么好处?

此时我们可以多创建几个实例

 function Person(name, age, sex) {
        this.name = name;
        this.age = age;
      }
      var xiaoming = new Person("小明", 18);
      var xiaohong = new Person("小红", 17);
      var xiaogang = new Person("小刚", 20);
      console.log(xiaoming,'xiaoming');
      console.log(xiaohong,'xiaohong');
      console.log(xiaogang,'xiaogang');

 

 

 

会发现他们拥有同样的属性群,称他们为同一类对象

new关键字调用的函数,此时都会返回同一类对象,感觉是在构造什么东西,此时这个函数我们称之为构造函数

  •  如果一个函数是构造函数,不是因为函数本身的执行能力,而是因为被new 关键字调用了
  •  默认首字母大写的函数,都知道该函数就是构造函数,如果首字母不大写,也不影响构造函数的功能
  •  构造函数能构造同一类对象,实例都拥有同样的属性群
  • 被构造函数new出来的对象我们叫做构造函数的实例

因为JavaScript是没有类的概念的(es6之前)所以JavaScript是基于面向对象的,此时我们可以模仿其他语言,把精髓移植过来。比如我们可以当上面Person函数中的Person视作个类(class),被new出来的

xiaoming就是是这个Person类的实例(instance)

 

 

 

实例调用方法会发生的问题

给Person类添加两个属性(name,age),每一个实例也可以有自己的方法。

此时调用函数写法就是 实例.方法(),因为实例本身就是一个对象,所以此时调用该方法的时候方法内部的this上下文就是这个对象

    function Person(name, age, sex) {
        this.name = name;
        this.age = age;
        this.sayHello = function () {
          console.log(this,this.name+'的this')
          console.log(
            "你好,我是" + this.name + ",今年" + this.age + "岁了,"
          );
        };
      }
      var xiaoming = new Person("小明", 18);
      var xiaohong = new Person("小红", 17);
      var xiaogang = new Person("小刚", 20);
      xiaoming.sayHello();
      xiaohong.sayHello();
      xiaogang.sayHello();

此时会发现,函数的上下文指向非常清楚,不会发生混乱,输出的都是该对象自己的上下文,规则2:对象打点调用函数的时候上下文就是这个对象,所以每一个this都是该实例本身

每一个实例本身都有一个sayHello函数

此时判断一下当前这些函数是否相等

console.log(xiaogang.sayHello === xiaohong.sayHello)

 

 

此时输出的是false,因为本质上是构造函数给每一个实例都添加另一个相同功能的函数,仅仅只是函数的功能相同,本质上不是一个函数

但是此时就会发现一个问题,因为函数本质就是提高复用性的,如果每一次创建一个实例的时候都添加一个函数,此时函数的复用性就被违背了,并且还会增加其他不属于自己的会用到的函数

 

 

 

 

比如我们有一个People类,这个类是描述所有的人类的职业方法,比如有程序员的方法xiedaima,比如有建筑师的方法是zaofangzi,比如有医生的方法是jiuren;如果此时我们创建一个chengxuyuan的实例,此

时这个实例不得不拥有不符合它的其他方法,并且一辈子都用不到

比如我们的构造函数会是这样

 function People(name, age, sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        // 程序员所用到的方法
        this.xiedaima = function () {};
        // 建筑师所用到的方法
        this.zoafangzi = function () {};
        // 医生所用到的方法
        this.jiuren = function () {};
      }
      var chengxuyuan = new People('小明', 24, '')
      console.log(chengxuyuan)

 

 

此时看上图会发现chengxuyuan本质没有其他的两个方法,但是必须要携带,所以代码会变成冗余,所以一般在原型上添加方法

 

posted @ 2022-01-03 21:23  keyeking  阅读(253)  评论(0编辑  收藏  举报