目录
- 对象创建的方式有哪些?
- 1. 工厂模式:
- 2. 构造函数模式:
- 3. 原型模式:
- 4. 混合模式:
- 5. 动态原型模式:
- 6. 寄生构造函数模式:
- 7. 字面量方式:
对象创建的方式有哪些?
JavaScript中创建对象的方式有多种,其中常用的有工厂模式、构造函数模式、原型模式、混合模式、动态原型模式和寄生构造函数模式。
1. 工厂模式:
使用一个函数封装创建对象的细节,通过调用函数来创建对象。但是对象无法和某个类型联系起来,缺乏类型识别。
function createPerson(name, age) {
let person = {} // 创建一个空对象
person.name = name // 给对象添加属性
person.age = age
person.sayHello = function () {
// 给对象添加方法
console.log("Hello, I'm " + this.name + '!')
}
return person // 返回对象
}
let person1 = createPerson('张三', 18) // 创建对象
let person2 = createPerson('李四', 20)
person1.sayHello() // 调用对象的方法
person2.sayHello()
在这个例子中,我们定义了一个 createPerson
函数,它接受两个参数 name
和 age
。在函数内部,我们创建了一个空对象 person
,并给它添加了两个属性 name
和 age
,以及一个方法 sayHello
。最后,我们返回这个对象。通过调用 createPerson
函数,我们可以创建多个对象,每个对象都有自己的 name
、age
和 sayHello
方法。
工厂模式的优点在于可以很好地封装对象的创建过程,从而提高代码的可维护性和可读性。但是,工厂模式无法识别对象的类型,因此无法使用 instanceof
运算符来判断对象的类型。另外,如果要添加新的方法或属性,需要修改工厂函数的代码,这可能会导致代码的不稳定性。
2. 构造函数模式:
使用构造函数模式创建对象,定义一个函数,通过 new
关键字调用函数,将 this
指向新建的对象,从而达到复用的目的。这种方式可以识别对象的类型。
function Person(name, age) {
this.name = name
this.age = age
this.sayHello = function () {
console.log("Hello, I'm " + this.name + '!')
}
}
let person1 = new Person('张三', 18) // 创建对象
let person2 = new Person('李四', 20)
person1.sayHello() // 调用对象的方法
person2.sayHello()
在这个例子中,我们定义了一个 Person
构造函数,它接受两个参数 name
和 age
。在函数内部,我们使用 this
关键字给对象添加了两个属性 name
和 age
,以及一个方法 sayHello
。使用 new
关键字调用构造函数时,会创建一个新的对象,并将 this
关键字指向这个新对象。最后,构造函数会返回这个新对象。通过调用 Person
构造函数,我们可以创建多个对象,每个对象都有自己的 name
、age
和 sayHello
方法。
构造函数模式的优点在于可以识别对象的类型,因此可以使用 instanceof
运算符来判断对象的类型。另外,如果要添加新的方法或属性,只需要在构造函数内部添加即可,这样更加灵活。但是,由于每个对象都会创建自己的方法,因此会占用更多的内存空间。
3. 原型模式:
使用原型对象来添加公用属性和方法,实现代码复用。每个函数都有一个 prototype 属性,使用原型模式创建对象,定义一个构造函数,将对象的属性和方法添加到构造函数的原型对象上。这种方式可以实现属性和方法的共享,从而节省内存空间。
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.sayHello = function () {
console.log("Hello, I'm " + this.name + '!')
}
let person1 = new Person('张三', 18) // 创建对象
let person2 = new Person('李四', 20)
person1.sayHello() // 调用对象的方法
person2.sayHello()
在这个例子中,我们定义了一个 Person
构造函数,它接受两个参数 name
和 age
。在函数内部,我们使用 this
关键字给对象添加了两个属性 name
和 age
。然后,我们将 sayHello
方法添加到构造函数的原型对象上。使用 new
关键字调用构造函数时,会创建一个新的对象,并将 this
关键字指向这个新对象。最后,构造函数会返回这个新对象。通过调用 Person
构造函数,我们可以创建多个对象,每个对象都有自己的 name
和 age
属性,以及共享的 sayHello
方法。
原型模式的优点在于可以实现属性和方法的共享,从而节省内存空间。由于每个对象共享同一个原型对象上的方法,因此不会占用额外的内存空间。另外,如果要添加新的方法或属性,只需要在原型对象上添加即可,这样更加灵活。但是,由于所有对象共享同一个原型对象,因此如果一个对象修改了原型对象上的属性或方法,会影响到其他对象。
4. 混合模式:
组合使用构造函数模式和原型模式,通过构造函数来初始化对象的属性,通过原型对象来实现函数方法的复用。结合构造函数模式和原型模式的优点,既可以识别对象的类型,又可以实现属性和方法的共享。
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.sayHello = function () {
console.log("Hello, I'm " + this.name + '!')
}
let person1 = new Person('张三', 18) // 创建对象
let person2 = new Person('李四', 20)
person1.sayHello() // 调用对象的方法
person2.sayHello()
function Student(name, age, grade) {
Person.call(this, name, age) // 继承属性
this.grade = grade
}
Student.prototype = Object.create(Person.prototype) // 继承方法
Student.prototype.constructor = Student // 修复 constructor
Student.prototype.study = function () {
console.log(this.name + ' is studying in grade ' + this.grade + '.')
}
let student1 = new Student('王五', 16, 10) // 创建对象
let student2 = new Student('赵六', 17, 11)
student1.sayHello() // 调用继承自 Person 的方法
student1.study() // 调用自己的方法
student2.sayHello()
student2.study()
在这个例子中,我们定义了一个 Person
构造函数,它接受两个参数 name
和 age
。在函数内部,我们使用 this
关键字给对象添加了两个属性 name
和 age
。然后,我们将 sayHello
方法添加到构造函数的原型对象上。使用 new
关键字调用构造函数时,会创建一个新的对象,并将 this
关键字指向这个新对象。最后,构造函数会返回这个新对象。通过调用 Person
构造函数,我们可以创建多个对象,每个对象都有自己的 name
和 age
属性,以及共享的 sayHello
方法。
接着,我们定义了一个 Student
构造函数,它继承自 Person
构造函数。使用 call
方法调用 Person
构造函数,将 this
关键字指向新建的 Student
对象,并传入 name
和 age
参数,从而继承了 Person
构造函数的属性。然后,我们将 Student
构造函数的原型对象指向一个新的 Person
构造函数的原型对象,从而继承了 Person
构造函数的方法。最后,我们添加了一个 study
方法,用于 Student
对象自己的行为。
使用 new
关键字调用 Student
构造函数时,会创建一个新的对象,并将 this
关键字指向这个新对象。最后,构造函数会返回这个新对象。通过调用 Student
构造函数,我们可以创建多个对象,每个对象都有自己的 name
、age
和 grade
属性,以及继承自 Person
构造函数的 sayHello
方法和自己的 study
方法。
混合模式的优点在于既可以识别对象的类型,又可以实现属性和方法的共享。通过继承构造函数模式的属性和原型模式的方法,可以更加灵活地创建对象。但是,由于需要继承两个部分的内容,因此代码量较多。
5. 动态原型模式:
动态原型模式是一种设计模式,用于在JavaScript中创建对象。它的主要思路是在构造函数内部判断是否需要初始化原型,如果需要,则在构造函数内部定义原型方法。将原型方法赋值的创建过程移动到构造函数的内部,通过对属性是否存在的判断,实现仅在第一次调用函数时对原型对象赋值一次的效果。
function Person(name, age) {
this.name = name
this.age = age
// 判断是否需要初始化原型
if (typeof this.sayHello !== 'function') {
// 定义原型方法
Person.prototype.sayHello = function () {
console.log('Hello, my name is ' + this.name + ' and I am ' + this.age + ' years old.')
}
}
}
// 创建两个Person对象
var person1 = new Person('Alice', 25)
var person2 = new Person('Bob', 30)
// 调用原型方法
person1.sayHello() // 输出: Hello, my name is Alice and I am 25 years old.
person2.sayHello() // 输出: Hello, my name is Bob and I am 30 years old.
在上述代码中,我们定义了一个Person
构造函数,它接受name
和age
作为参数,并将它们赋值给实例变量。然后,我们使用动态原型模式来检查是否需要初始化原型方法sayHello
。如果原型中不存在sayHello
方法,那么我们就在构造函数内部定义该方法。
这样做的好处是,每次创建新的Person
对象时,不会重复地定义原型方法。只有在第一次创建对象时,才会初始化原型方法。这样可以节省内存,并且避免了每个实例都拥有相同的原型方法的副本。
通过使用动态原型模式,我们可以灵活地定义构造函数和原型方法,并确保它们在需要的时候被正确地初始化。
6. 寄生构造函数模式:
寄生构造函数模式是一种设计模式,它通过在一个普通的构造函数内部创建并返回一个新对象,从而实现对构造函数的扩展。这个新对象通常被称为"寄生对象"。
function Person(name, age) {
var obj = {} // 创建一个空对象
// 对空对象进行属性和方法的添加
obj.name = name
obj.age = age
obj.sayHello = function () {
console.log('Hello, my name is ' + this.name + ' and I am ' + this.age + ' years old.')
}
return obj // 返回新创建的对象
}
// 创建一个Person对象
var person = new Person('Alice', 25)
// 调用对象的方法
person.sayHello() // 输出: Hello, my name is Alice and I am 25 years old.
在上述代码中,我们定义了一个Person
构造函数,它接受name
和age
作为参数。在构造函数内部,我们创建了一个空对象obj
,并向其添加了name
、age
属性以及sayHello
方法。
最后,我们将新创建的对象obj
返回,作为构造函数的结果。这样,在调用new Person()
时,会得到一个包含了指定属性和方法的新对象。
使用寄生构造函数模式可以在不改变原始构造函数的情况下,对其进行扩展。这种模式常用于需要在原始构造函数的基础上添加额外功能或修改返回对象的情况下。然而,需要注意的是,寄生构造函数模式会导致每个新对象都拥有自己的方法副本,可能会造成内存浪费。因此,在使用该模式时要谨慎考虑其适用性和性能影响。
7. 字面量方式:
字面量方式是一种直接使用花括号{}
来定义对象的方式。
// 创建一个对象并定义属性和方法
var person = {
name: 'Alice',
age: 25,
sayHello: function () {
console.log('Hello, my name is ' + this.name + ' and I am ' + this.age + ' years old.')
}
}
// 访问对象的属性和调用方法
console.log(person.name) // 输出: Alice
console.log(person.age) // 输出: 25
person.sayHello() // 输出: Hello, my name is Alice and I am 25 years old.![请添加图片描述](https://img-blog.csdnimg.cn/direct/89a64e636e56468bb8d122c13b5c64d7.png)
在上述代码中,我们使用字面量方式创建了一个名为person
的对象。通过花括号{}
,我们直接在对象内部定义了属性name
和age
,以及方法sayHello
。
然后,我们可以通过点号.
来访问对象的属性,例如person.name
和person.age
。同时,我们也可以使用person.sayHello()
来调用对象的方法。
字面量方式创建对象简单明了,适合创建单个对象或者只需要临时使用的对象。它不需要使用构造函数或原型,并且可以直接在对象内部定义属性和方法,非常方便。然而,由于每次创建对象都需要重新定义属性和方法,所以不适合创建大量相似的对象,这种情况下可以考虑使用其他方式,如构造函数或工厂模式。
总结:JavaScript中创建对象的方式有多种,每种方式都有其特点和适用场景,根据实际情况选择合适的方式来创建对象。工厂模式、构造函数模式、原型模式、混合模式、动态原型模式和寄生构造函数模式都是常用的创建对象的方式。在选择创建对象的方式时,需要注意代码的可读性、可维护性和性能等方面。
持续学习总结记录中,回顾一下上面的内容:
对象创建的方式有很多种。比较常见的包括工厂模式(像工厂一样创建对象)、构造函数模式(使用函数初始化对象)、原型模式(通过原型克隆对象)、混合模式(结合多种方式创建对象)、动态原型模式(在运行时扩展对象功能)、寄生构造函数模式(在构造函数内部创建对象并返回)、字面量方式(直接使用{}创建对象)。这些方式各有特点,可以根据具体需求选择最适合的方式来创建对象。