美文网首页JavaScript那些事
js基础阵营:变量篇之特殊变量-对象的创建

js基础阵营:变量篇之特殊变量-对象的创建

作者: 来瓶二锅头00 | 来源:发表于2022-04-04 16:01 被阅读0次

    上一章,我们说到了对象的一些基本的属性,这一章,我们来看下如何去创建一个对象。
    在js中创建对象有两种方式,一种是单纯的通过对象字面量的方式,一种是复杂的方式。

    1.对象字面量

    通过定义变量饿方式来创建一个对象。以上一章的房子图纸为例

    var house = new Object();
    house.name = '二锅头的房子';
    house.money = 2000;
    

    这样就创建了一个house对象,当时这种方法存在一个问题,那就是如果我们要创建多个house,我们就需要重复大量的代码,这样会造成代码的冗余。因此我们有了一系列的复杂的方式

    2. 复杂方式

    2.1 工厂模式

    工厂模式是在所有的程序设计中一种广为人知的设计模式,通过一个类来抽象创建具体对象的过程。由于js中无法创建类,因此我们需要通过一个函数,在函数中封装特定的对象。就跟工厂一样,外人不需要知道如何生产,只需要给出需要的东西,工厂就会生产出所需要的的东西。同样以上面的房子为例

    function createHouse(name,money) {
      var obj = new Object();
      obj.name = name;
      obj.money = money;
      obj.showInfo = function() {
        console.log(obj.name + '价格是:' + obj.money);
      }
      return obj;
    }
    var house = createHouse('二锅头的房子',20000000);
    

    这样我们就创建了一个house对象,但是用这种方法会有一个问题,那就是我们无法获取这个对象的类型,因为无论怎么判断,返回的永远是object.因此有了通过构造函数模式的方法

    2.2 构造函数方法

    在js中,针对Object底层有默认的构造函数,当我们通过new来创建对象的时候,底层会自动执行构造函数。从而创建对象。我们来看下面的例子

    var house = new Object();
    house.name = '来瓶二锅头';
    

    上面的方法,在底层的时候,会经历以下4个步骤

    1. 创建一个虚拟的新对象
    2. 将Object的内置构造函数赋值给新对象
    3. 执行内置构造函数的代码
    4. 返回新对象给house

    同时js也支持我们自己自定义构造函数,从而通过在构造函数中自定义对象的属性以及方法。因此我们可以借助此方法来通过构造函数方法来创建对象。同样以房子为例

    function createHouse(name,money) {
      this.name = name;
      this.money = money;
      this.showInfo = function() {
        console.log(this.name + '价格是:' + this.money);
      }
    }
    var house = new createHouse('二锅头的房子',20000000);
    var house2 = new createHouse('二锅头的房子2',2000000000);
    

    同样的我们可以创建对象,同样的我们来看下执行步骤

    1. 通过new操作符创建一个新对象。
    2. 将构造函数的作用域赋值给新对象,因此this指向的为新的对象
    3. 执行构造函数,也就是createHouse方法
    4. 返回新对象给house

    我们知道在工厂模式的时候是因为无法判断对象类型,所以我们就有了构造函数方法。那么我们如何判断呢?
    在上面我们说过了每个对象都有构造函数,因此我们可以通过对象属性constructor来判断。所以我们看下以下代码

    house.constructor == createHouse; // true
    house2.constructor == createHouse;// true
    

    结果都为true,因此我们可以通过constructor属性来获取对象类型(因为constructor指向的是createHouse)。
    但是构造函数方式会存在一个弊端,那就是我们每创建一个实例的时候,内部的方法都需要实例化一下,同样以上面的例子,每创建一个house,我们就需要实例化一个showInfo方法,这样同样容易造成代码的冗余,因此我们就有了另一种方法,通过原型的模式

    2.3 原型模式

    要明白如何通过原型的方法创建对象,首先我们需要知道什么是原型,以及原型的原理。下面我们来一一剖析。
    在构造函数方法里我们说过了我们会将构造函数赋值给新对象,那么如何赋值的呢?其实就是通过原型的方式。因为在我们所有的对象中都有一个property的属性。这个属性是一个指向一个对象的属性(有些书中会说是一个指针,但是实际上js中没有指针的概念,只是其他语言中用习惯了。)因此我们可以将所有共享的属性和方法都放在这个属性下,当通过构造函数指向这个属性的时候,我们创建对象的时候就可以使用所有的属性和方法,而不必都放在构造函数中。还是有点绕。我们依旧以上面的例子来看看

    function House() {}
    House.property.name = '二锅头的房子';
    House.property.money = '2000000';
    House.property.showInfo = function(){
     console.log(this.name + '价格是:' + this.money);
    }
    var house = new House();
    house.showInfo();
    var house2 = new House();
    house2.showInfo();
    

    我们可以看到其实打印出来的结果是一样的,说明我们都是调用的同一个函数,因此构造函数方式存在的问题解决了。下面我们来一点点的来看下上面的方法如何实现的

    1. 通过new House()方法,创建一个对象,我们假定对象名为obj.
    2. 将构造函数constructor赋值给新对象,也就constructor(House方法)指向obj.
    3. 执行构造函数
    4. 将原型上的属性和方法以及执行过的构造函数一并返回给house

    上面4步,可以用下图进行表示


    image.png

    我们来一一说明

    1. new House创建一个House对象,此对象拥有一个构造函数,House方法,同时其拥有一个原型(property)属性,此原型拥有2个属性,name,money以及一个方法showInfo
    2. 将构造函数赋值给House对象,也就是通过constructor指向House
    3. 执行构造函数方法,
    4. 将对象返回给house实例,也就是通过house实例的原型指向House对象即可
      因此其实上面的方法我们还可以通过另一种事项方法
    function House() {}
    House.property = {
      constructor:House,
      name: '二锅头的房子',
      money:2000000,
      showInfo: function(){
       console.log(this.name + '价格是:' + this.money);
      }
    }
    var house = new House();
    house.showInfo();
    var house2 = new House();
    house2.showInfo();
    

    通过这种方式应该会可以更加清楚明白上面的解释了。通过原型的方式解决了上面构造函数的问题,但是依旧会存在一个问题,那就是由于属性是完全共享的,如果其中一个属性是对象或者数组,就会导致两个实例的值一样,其中一个修改,另一个也同样会修改。例如

    function House() {}
    House.property = {
      constructor:House,
      name: '二锅头的房子',
      money:2000000,
      member:['二锅头']
      showInfo: function(){
       console.log(this.name + '价格是:' + this.money);
      }
    }
    var house = new House();
    house.showInfo();
    var house2 = new House();
    house2.showInfo();
    house2.member.push('五粮液');
    console.log(house.member); // 二锅头,五粮液
    

    因此产生了另一种方式,那就是组合构造函数和原型的方式

    2.4 构造函数+原型组合方式

    前面我们说到了构造函数可以设置自定义属性,原型方式可以设置共享的属性以及方法,那么我们可以将其结合,这样就能满足需求了,同样以上面的为例

    function House(name,money,member) {
      this.name = name;
      this.money = money;
      this.member = member;
    }
    House.property = {
      constructor:House,
      showInfo: function(){
       console.log(this.name + '价格是:' + this.money);
      }
    }
    var house = new House();
    house.showInfo();
    var house2 = new House();
    house2.showInfo();
    house2.member.push('五粮液');
    console.log(house.member); // 二锅头
    

    此方法是当前最流行的方案。
    至此常见的对象的创建就介绍完成了。还有两种不常见的方法,个人觉得没有必要去学习。所以感兴趣的可以去自己学习下哦

    相关文章

      网友评论

        本文标题:js基础阵营:变量篇之特殊变量-对象的创建

        本文链接:https://www.haomeiwen.com/subject/wekksrtx.html