• JS创建对象的十种方式


    本文节选自我的博客:JS创建对象的十种方式

    • 💖 作者简介:大家好,我是MilesChen,偏前端的全栈开发者。
    • 📝 CSDN主页:爱吃糖的猫🔥
    • 📣 我的博客:爱吃糖的猫
    • 📚 Github主页: MilesChen
    • 🎉 支持我:点赞👍+收藏⭐️+留言📝
    • 💬介绍:The mixture of WEB+DeepLearning+Iot+anything🍁

    前言

    面向对象是一种重要的编程范式,如何灵活的创建对象,是对编程基本功的考验,本来我们来探讨创建对象的十种方式。我将这十种分为new Object、构造函数与原型对象、其他三个大类。

    new Object

    这三种本质都是new Object,他们无法根据对象的原型对象准确判断对象的类型,因为原型对象上都是Object。console.log(obj.__proto__===Object.prototype); // true

    new Object

    const obj = new Object({name: 'wayne',age: 18})

    字面量方式

    const obj = {name: 'wayne',age: 18}

    工厂函数方式

    function createPerson(name, age) {
     	return {name,age,}
    }
     const obj = createPerson('wayne', 18)
    
    • 1
    • 2
    • 3
    • 4

    构造函数与原型对象

    这四种是对构造函数与原型对象创建对象上的细化。

    构造函数方式

    如果构造函数中包含的方法,则会重复创建,造成内存的浪费(只适合放属性不适合方法)

    function Person(name, age) {
    	this.name = name
        this.age = age
        this.getInfo = function() {
            console.log(this.name, this.age)
        }
    }
    const obj = new Person('wayne', 18)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    原型对象方式

    合放方法:将共同的方法放到原型当中可以避免重新创建相同功能的方法,减少了内存的使用。
    不适合放属性:原因有三条

    1. new初始化新的属性时候不方便,
    2. 修改起来不方便 p1.__proto__.name = 'jack'
    3. 在原型对象的属性会在所有的对象上共享,导致新new出来出现问题
    function Person() {}
    Person.prototype.name = "wayne"
    Person.prototype.age = 10
    Person.prototype.getInfo = function() {
    	console.log(this.name, this.age)
    }
    const p1 = new Person()
    // 这里使用的是原型上的属性
    p1.getInfo() // wayne 10
    // 修改原型上的属性
    p1.__proto__.name = 'jack'
    p1.__proto__.age = 18
    // 这里使用的是原型上的属性
    p1.getInfo() // jack 18
    
    const p2 = new Person()
    // 修改过的属性
    p2.getInfo()  // jack 18
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    混合模式

    这是我们常见的方式,将属性放在构造函数,方法放在原型上。但这种方式不太符合面向对象封装的思想。

    function Person(name, age) {
    	this.name = name
      this.age = age
    }
    Person.prototype.getInfo = function() {
    	console.log(this.name, this.age)
    }
    const p1 = new Person(name, age)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    动态混合

    其实就是混合模式的改进,这种方式的缺点是语义不符,其实只有第一个对象创建时才会走 if 判断

    function Person(name, age) {
    	this.name = name
      this.age = age
      if (Person.prototype.getInfo === "undefined") {
      	Person.prototype.getInfo = function() {
        	console.log(this.name, this.age)
        }
      }
    }
    // 第一次调用时会给 Person.prototype 添加 getInfo 方法
    const p1 = new Person("wayne", 18) 
    const p2 = new Person("jack", 15)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    寄生构造函数

    和动态混合一样,但通过函数里调用其他构造函数

    function Person(name, age) {
    	this.name = name
        this.age = age
        if (Person.prototype.getInfo === "undefined") {
            Person.prototype.getInfo = function() {
                console.log(this.name, this.age)
            }
        }
    }
    function func(name, age) {
    	const p = new Person(name, age)
        return p
    }
    const p1 = func("wayne", 18)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    其他

    class

    使用ES6语法糖class创建对象,其实class的本质就是function。

    class Person {
    	constructor(name, age) {
      	this.name = name
        this.age = age
      }
      getInfo() {
      	console.log(this.name, this.age)
      }
    }
    const p1 = new Person("wayne", 18)
    // class的本质是function
    console.log(typeof Person);  //function   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    闭包

    利用闭包的特性,也可以实现创建对象。优点:不用this 和 new;缺点:容易造成内存泄漏。

    function Person(name, age) {
        return {
          getName() {
              return name
          },
          getAge: function() {
              return age
          }
        }
    }
    const p1 = Person("wayne", 18)
    console.log(p1.getName()) // wayne
    console.log(p1.getAge()) // 18
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    总结

    new Object的三种

    1. new Objectnew Object({name: 'wayne',age: 18})
    2. 字面量创建:{name: 'wayne',age: 18}
    3. 工厂函数方式:function createPerson(name, age) {return {name,age,}}

    构造函数与原型对象四种

    1. 构造函数方式:适合属性
    2. 原型对象方式:适合方法
    3. 混合方式:常见的方式,将属性放在构造函数,方法放在原型上。
    4. 动态混合:使用if判断是否挂载方法
    5. 寄生构造函数:通过函数里调用其他构造函数

    其他两种

    1. class,ES6语法糖,本质为function
    2. 闭包:优点:不用this 和 new;缺点:容易造成内存泄漏。

    感谢小伙伴们的耐心观看,本文为笔者个人学习记录,如有谬误,还请告知,万分感谢!如果本文对你有所帮助,还请点个关注点个赞~,您的支持是笔者不断更新的动力!

  • 相关阅读:
    XCKU5P-2FFVB676E 赛灵思FPGA可编程逻辑芯片器件 XILINX
    项目开发中Maven的单向依赖-2022新项目
    以太坊是什么? 以及以太坊如何工作的?
    Node.js 入门教程 19 package-lock.json 文件
    惊艳!Linux 中迷人的 Shell 脚本工具
    如何查看硬盘对应的主板接口属性
    近期总结2023.10.16
    Servlet学习日志
    GreenPlum DB向GBase迁移_TIME类型
    endnote21从安装到使用!文献引用!Mac版
  • 原文地址:https://blog.csdn.net/weixin_42745647/article/details/133561853