前言在JavaScript的世界里有一句广为人知的话——“万物皆对象”。无论是我们日常使用的字符串、数字还是自定义的函数、数组本质上都和“对象”有着千丝万缕的联系。但很多新手在学习对象时总会被“构造函数”“new关键字”“包装类”这些概念绕晕今天就结合具体代码实例用通俗易懂的语言把JS对象的核心知识点讲明白、讲透彻。一、先搞懂什么是对象对象Object是JS中最核心的数据类型之一它就像一个“收纳盒”可以存放多个不同类型的数据我们称之为“属性”和可执行的操作我们称之为“方法”。比如一个“人”可以有姓名、年龄属性可以吃饭、睡觉方法一辆车可以有颜色、尺寸属性可以行驶、刹车方法对象就是用来描述这种“具有多种特征的事物”的。在JS中数据类型分为两大类这也是理解对象的基础原始类型简单数据类型无法拥有属性和方法包括string字符串、number数字、bool布尔值、undefined未定义、null空值、Symbol唯一值、bigInt大整数。引用类型复杂数据类型本质上都是对象能拥有属性和方法包括函数function、数组array、普通对象object等。这里要注意一个易错点原始类型一定无法添加属性和方法属性和方法是对象独有的后面我们会通过“包装类”详细解释这一点二、3种创建对象的方式日常开发中我们创建对象的方式主要有3种各自有不同的使用场景结合代码实例一看就懂1. 对象字面量 {}最简洁常用这是最直观、最常用的创建方式用大括号{}包裹属性和值属性和值之间用冒号:分隔多个属性之间用逗号,分隔适合创建单个、简单的对象。// 实例1创建一个“人物”对象 const person { name: 米奇, // 属性姓名值为字符串 age: 18, // 属性年龄值为数字 sayHi: function() { // 方法打招呼 console.log(你好呀我是米奇); } } console.log(person); // 输出{ name: 米奇, age: 18, sayHi: [Function: sayHi] } person.sayHi(); // 调用方法输出你好呀我是米奇 // 实例2创建一个空对象后续添加属性 const obj {}; obj.name 米妮; obj.age 17; console.log(obj); // 输出{ name: 米妮, age: 17 }2. new Object()构造函数创建 ️这是通过JS内置的构造函数Object()创建对象本质和对象字面量一样只是写法更繁琐适合动态添加属性的场景。// 实例用new Object()创建对象并动态添加属性 const obj new Object(); // 先创建一个空对象 obj.name 米妮; // 给对象添加name属性 const abc age; // 用变量作为属性名 obj[abc] 18; // 动态添加age属性括号语法适合属性名是变量的场景 console.log(obj); // 输出{ name: 米妮, age: 18 } // delete关键字删除对象的属性 delete obj[abc]; // 删除age属性 console.log(obj); // 输出{ name: 米妮 }这里补充一个小知识点delete关键字只能删除对象的属性不能删除变量而且删除后再访问该属性会返回undefined。3. new 调用自定义构造函数批量创建对象当我们需要批量创建多个结构相同的对象比如多个用户、多辆车时用前面两种方式就太繁琐了——这时候自定义构造函数就派上用场了先明确一个概念当一个函数被 new 关键字调用时这个函数就被称为“构造函数”。构造函数的命名规范是首字母大写区分普通函数目的是为了批量生成具有相同属性结构的对象。// 实例1自定义构造函数Person批量创建人物对象 function Animal(name, age, role) { // this指向当前创建的对象给对象添加属性 this.name name; this.age age; this.role role; // 也可以添加方法 this.introduce function() { console.log(我是${this.name}今年${this.age}岁我的角色是${this.role}); } } // new调用构造函数创建2个实例对象 const p1 new Animal(米奇, 8, animal); const p2 new Animal(跳跳虎, 9, tigger); console.log(p1); // 输出Animal { name: 米奇, age: 8, role: animal, introduce: [Function (anonymous)] } console.log(p2); // 输出Animal { name: 跳跳虎, age: 9, role: tigger, introduce: [Function (anonymous)] } p1.introduce(); // 调用方法输出我是米奇今年8岁我的角色是animal // 实例2自定义构造函数Car批量创建汽车对象 function Car(color) { // 固定属性所有汽车都一样 this.name su7; this.height 1400; this.lang 4800; this.weight 1500; // 动态属性不同汽车可以不一样 this.color color; } // 批量创建2辆汽车 const car1 new Car(purple); // 紫色的su7 const car2 new Car(pink); // 粉色的su7 const car3 Car(pink); // 粉色的su7 console.log(car1); // 输出Car { name: su7, height: 1400, lang: 4800, weight: 1500, color: purple }易错点提醒构造函数必须用new调用如果忘记写new函数会变成普通函数this会指向全局浏览器中是windowNode环境中是global此时返回值是undefined。错误示例忘记new调用Car函数 const car3 Car(black); console.log(car3); // 输出undefined因为普通函数没有return值三、重点突破new关键字到底干了什么 很多新手都会疑惑为什么用new调用构造函数就能创建出对象其实new关键字背后只做了3件事简单好记结合代码拆解创建一个空的this对象相当于执行const _this {}这个空对象就是未来要返回的实例对象。执行构造函数中的代码给this对象添加属性把构造函数中this.xxx的内容都添加到第一步创建的空对象上。返回这个this对象不需要我们手动写returnnew会自动把添加好属性的this对象返回赋值给变量。我们可以用一段“模拟new操作”的代码更直观地理解这个过程// 模拟new关键字的作用手动实现构造函数的逻辑 function car() { // 1. 创建一个空对象对应new的第一步 const _this {}; // 2. 给空对象添加属性对应new的第二步 _this.name su7; _this.color green; // 3. 返回这个对象对应new的第三步 return _this; } // 调用函数得到实例对象相当于new person() const obj car(); console.log(obj); // 输出{ name: su7, color: green }new的核心就是“自动帮我们创建对象、添加属性、返回对象”省去了我们手动写这些重复代码的麻烦四、易错点包装类为什么原始类型不能加属性 前面我们说过“原始类型一定无法添加属性和方法”但很多新手会写出这样的代码然后疑惑为什么结果不符合预期// 看似给数字添加属性实则无效 var num 123; num.a aaa; // 尝试给原始类型num添加属性a delete num.a; // 尝试删除属性a console.log(num.a); // 输出undefined // 看似给字符串添加属性实则无效 var str hello; str.len 2; // 尝试给原始类型str添加属性len console.log(str.len); // 输出undefined这就涉及到JS中的“包装类”Wrapper Class概念其实V8引擎在背后做了“隐式操作”我们拆解一下过程什么是包装类包装类是JS内置的、对应原始类型的构造函数包括String()、Number()、Boolean()。它们的作用是当我们对原始类型进行“属性操作”时引擎会自动把原始类型转换成对应的包装类实例对象操作完成后再自动销毁这个实例对象——这就是“自动装箱”和“自动拆箱”。拆解上面的错误示例var num 123; // 原始类型number num.a aaa; // 引擎隐式操作 // 1. 自动装箱new Number(123).a aaa创建包装类实例添加属性 // 2. 操作完成后自动销毁这个实例对象 delete num.a; // 同样隐式创建实例删除属性后销毁 console.log(num.a); // 再次隐式创建新的实例新实例没有a属性所以返回undefined核心总结当我们定义一个原始类型字面量如var str helloV8引擎默认执行的还是new String(hello)创建包装类实例但会自动拆箱成原始类型。包装类的实例对象参与运算时会自动拆箱成原始类型比如123 new Number(456) 579。JS是弱类型语言只有在赋值语句执行时才会判断值的类型当值被判定为原始类型时就会自动将包装对象上添加的属性移除——所以我们给原始类型加属性永远无效。五、总结核心知识点梳理 看完上面的内容相信你已经掌握了JS对象的核心知识点我们用一张表格快速梳理方便记忆知识点核心内容关键提醒对象本质存放属性和方法的“收纳盒”引用类型的核心万物皆对象但原始类型不是对象创建方式1. 对象字面量 {}2. new Object()3. new 自定义构造函数批量创建用自定义构造函数new的作用1. 创建this空对象2. 执行构造函数添加属性3. 返回this对象构造函数必须用new调用包装类原始类型属性操作时的隐式实例操作后自动销毁原始类型无法添加属性和方法 最后提醒JS对象是前端开发的基础后续的原型、原型链、继承等知识点都建立在对象的基础上。祝大家学习顺利写出更优雅的JS代码