你认识JS对象吗?
文章摘要
对象是JavaScript中包含数据和方法的集合,通常由属性和方法组成。根据ECMA-262定义,对象是属性的无序集合,每个属性或方法由名称映射到值。创建对象的方法包括:
new操作符和Object构造函数:语法为let person = new Object();,适用于简单场景,但每次创建都需要重复代码。
对象字面量:语法为let person = {};,简化了语法,但需手动添加属性和方法。
工厂模式:通过函数创建特定对象,解决重复创建问题,但未解决对象标识问题。
构造函数模式:通过定义属性和方法,确保实例化为特定类型,但构造函数内部的函数会被多次创建,导致同名函数不相等。
每种方法都有其适用场景,但均存在不足,后续内容将介绍更全面的解决方案。
文章目录
根据ECMA-262标准,对象被定义为属性的无序集合。这表明对象仅包含一组无序的值。每个属性或方法都通过一个==名称==来标识,这个==名称==映射到一个==值==。
注
- 🔰 总结
前言
注意:本篇内容需要你熟悉几个常见的概念,请看上篇 《写在初识对象前!!》
一、对象是什么?
对象可以被视为一个包含数据和操作的集合体,由一组字段和操作组成,在编程中,我们通常将对象的属性和方法称为对象的属性和方法。
按照ECMA-262的规定,对象被定义为属性的无序集合。从严格意义上说,这意味着对象就是一组没有特定顺序的值。每个属性或方法都通过名称来标识,这个名称映射到一个值。每个属性或方法都通过名称来标识,这个名称映射到一个值。
二、创建对象的方法
🌴 1. 使用 new 操作符和 Object 构造函数
🚩 语法:let person = new Object();
例如:
// new 操作符跟 Object 构造函数
let person = new Object(); // 与 let person = {} 相同
person.name = "袁华";
person.age = 29;
person.sayName = function () {
console.log(`你好!我是 ${this.name}。`);
};
早期JavaScript 开发者普遍倾向于使用 new Object() 这一机制来创建对象。然而,由于每次调用都需要明确写出 new Object(),这种做法显得繁琐。幸运的是,随着技术的发展,对象字面量逐渐演变为一种更简洁的表示方式。值得注意的是,这种简化的表示方法实际上是一种 语法糖,即 new Object() 的高级封装形式。
🌴 2. 对象字面量(object literal)表示法
对象字面量是一种简写方式,其主要目的是简化创建包含大量属性的对象的过程。对象字面量由一对大括号{ }包裹起来,包含键值对的集合。
🚩 语法:let person = {};
例如:
// 对象字面量 (object literal)
let person = {
name: ["夏洛", "马冬梅"],
age: 32,
bio() {
console.log(`${this.name[0]} 和 ${this.name[1]} 现在 ${this.age} 岁了。`);
},
introduceSelf() {
console.log(`你好!我是 ${this.name[0]}。`);
},
};
person对象中的属性值可以是任意类型的数据,其中包含一个数字、一个数组以及两个操作项。前两项属于对象的属性,而后面两项属于对象的方法。
不足
实际上,尽管前面介绍了两种创建 Object 实例的方法,但开发者更倾向于使用对象字面量表示法。这得益于对象字面量代码简洁,同时能够更直观地体现封装所有相关数据的特点。
| 因为上面介绍的 2种方式 都存在明显的不足,所以新的模式由此产生,即:工厂模式 。 |
|---|
🍄 3. 工厂模式
工厂模式是一种广为人知的设计模式,在软件工程领域中得到了广泛应用,用于抽象地创建特定对象的过程。
下面的例子展示了一种【用函数来封装以特定接口】创建对象的方式:
function createPerson(name, age) {
let obj = new Object();
obj.name = name;
obj.age = age;
obj.sayName = function () {
console.log(`你好!我是 ${this.name}。`);
};
return obj;
}
let person1 = createPerson("夏洛", 32);
let person2 = createPerson("马冬梅", 30);
在这里,函数 createPerson() 接受两个参数,基于这些参数生成了一个包含Person信息的对象。通过使用不同的参数组合,可以多次调用该函数,每次调用都会返回一个包含两个属性和一个方法的对象。
该工厂模式虽然能够处理创建多个类似对象的问题,但未能解决对象标识问题,即新创建的对象属于何种类型。
于是,随着 JavaScript 的发展,由一个新模式出现了 - - > 构造函数模式 。
🍄 4. 构造函数模式
ECMAScript 中的构造函数是用于创建特定类型对象的。像 Object 和 Array 这样的原生构造函数 ,运行时可以直接在执行环境中使用。
当然也可以自定义构造函数,以函数的形式为自己的对象类型定义 属性 和 方法 。
比如,上一个例子使用构造函数模式可以这样写:
function Person(name, age) {
this.name = name;
this.age = age;
this.sayName = function () {
console.log(`你好!我是 ${this.name}。`);
};
}
let person1 = new Person("夏洛", 32);
let person2 = new Person("马冬梅", 30);
person1.sayName(); // 你好!我是 夏洛。
person2.sayName(); // 你好!我是 马冬梅。
在本例中,Person() 构造函数 替代了 createPerson()工厂函数 。值得注意的是,Person() 内部的代码基本上一致于 createPerson() ,但存在一些差异。
🔸 没有显式地创建对象。
🔸 属性 和 方法 直接赋值给了 this。
🔸 没有 return。
Person的首字母大写了,按照惯例,构造函数名称的首字母通常大写,而非构造函数则以小写字母开头——(行业规范)这样有助于在ECMAScript中区分构造函数和普通函数。
为创建 Person 实例 ,应采用 new 操作符 。该方法将执行以下操作:( **new 的作用是什么?????)
💥💥💥 重要:
1️⃣ 生成一个新的对象到内存中。
2️⃣ 该新对象的 prototype 属性被设置为构造函数的 prototype 属性。
3️⃣ 在构造函数内部,this 指针指向该新对象。
4️⃣ 运行构造函数内部的代码以添加对象属性。
5️⃣ 如果构造函数返回非空对象,则返回该对象;否则,返回刚生成的新对象。
person1和person2各自存储了不同实例的Person对象,每个对象都具有一个**constructor属性**指向Person类。
console.log(person1.constructor == Person); // true
console.log(person2.constructor == Person); // true
constructor 本来是用于标识对象类型的。不过,普遍认为 instanceof 操作符 是确定对象类型更可靠的方式。前面例子中的每个对象都是 Object 的实例,同时也是 Person 的实例,如下调用 instanceof 操作符 的结果表明:
console.log(person1 instanceof Object); // true
console.log(person1 instanceof Person); // true
console.log(person2 instanceof Object); // true
console.log(person2 instanceof Person); // true
定义自定义构造函数【确保实例被明确标识为特定类型
尽管构造函数具有一定的价值,但它们也存在一些问题。其主要问题在于,每次定义方法都会在每个实例上创建一次。因此,在前面的例子中,person1和person2都拥有名为sayName()的方法,但这些方法并非同一个Function实例。我们都知道,在ECMAScript中,函数被视为对象,因此每次定义函数都会初始化一个新的对象。
function Person(name, age) {
this.name = name;
this.age = age;
this.sayName = new Function( "console.log(`你好!我是 ${this.name}。`)" ); // 逻辑等价
}
let person1 = new Person("夏洛", 32);
let person2 = new Person("马冬梅", 30);
person1.sayName(); // 你好!我是 夏洛。
person2.sayName(); // 你好!我是 马冬梅。
明明是做的同一件事情,不同实例上的 函数虽然同名却不相等 ,如下所示:
console.log(person1.sayName == person2.sayName); // false
看到这里是不是跟这个表情包一样?

列举了诸多方式,各自存在不足,那是否有一种方式能够包容所有不足呢?
答案: 肯定有了啊,程序员的智慧可是无止境的,哪里不足补哪里~~,静待更新。。。
🔰 总结
🎉🎉:知其然,才能知其所以然。不想再做搬运工,后续会持续更新~~
