Object creation methods
Object Literals
Object literals are the simplest and most straightforward way to create objects, using curly braces {}
to enclose key-value pairs. This approach is suitable for creating simple, non-reusable objects.
const person = {
name: 'Zhang San',
age: 30,
greet() {
console.log(`Hello, I am ${this.name}`);
}
};
Object literals support various value types as property values, including functions, arrays, and other objects. Since ES6, computed property names are also supported:
const propKey = 'gender';
const person = {
[propKey]: 'male',
['user' + 'Name']: 'Li Si'
};
Constructor Functions
Using the new
keyword to call a constructor function creates an object instance. This approach is suitable for scenarios where multiple similar objects need to be created.
function Person(name, age) {
this.name = name;
this.age = age;
this.greet = function() {
console.log(`Hello, I am ${this.name}`);
};
}
const person1 = new Person('Wang Wu', 25);
const person2 = new Person('Zhao Liu', 28);
The issue with constructor functions is that each instance creates its own copy of methods, leading to memory waste. The solution is to define methods on the prototype:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.greet = function() {
console.log(`Hello, I am ${this.name}`);
};
Object.create()
The Object.create()
method uses an existing object as the prototype for the newly created object. This approach is suitable for scenarios requiring precise control over the object's prototype chain.
const personProto = {
greet() {
console.log(`Hello, I am ${this.name}`);
}
};
const person = Object.create(personProto);
person.name = 'Qian Qi';
person.age = 35;
A second parameter can be passed to define property descriptors:
const person = Object.create(personProto, {
name: {
value: 'Sun Ba',
writable: true,
enumerable: true
},
age: {
value: 40,
enumerable: true
}
});
Class Syntax
ES6 introduced class syntax, which is essentially syntactic sugar over constructor functions but provides a clearer way to write object-oriented code.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, I am ${this.name}`);
}
static createDefault() {
return new Person('Default', 0);
}
}
const person = new Person('Zhou Jiu', 45);
const defaultPerson = Person.createDefault();
Classes support inheritance, static methods, getters/setters, and other features:
class Employee extends Person {
constructor(name, age, position) {
super(name, age);
this.position = position;
}
get info() {
return `${this.name}(${this.age}) - ${this.position}`;
}
}
Factory Functions
Factory functions are functions that return objects and do not require the new
keyword. This approach is suitable for scenarios requiring encapsulation of complex creation logic.
function createPerson(name, age) {
return {
name,
age,
greet() {
console.log(`Hello, I am ${this.name}`);
}
};
}
const person = createPerson('Wu Shi', 50);
Private members can be created using closures:
function createPerson(name) {
let _age = 0; // Private variable
return {
name,
get age() {
return _age;
},
set age(value) {
if(value >= 0) {
_age = value;
}
}
};
}
Singleton Pattern
The singleton pattern ensures that a class has only one instance. In JavaScript, this can be implemented using an Immediately Invoked Function Expression (IIFE).
const Singleton = (function() {
let instance;
function createInstance() {
return {
id: Math.random(),
log() {
console.log(`Instance ID: ${this.id}`);
}
};
}
return {
getInstance() {
if(!instance) {
instance = createInstance();
}
return instance;
}
};
})();
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true
Object Destructuring and Merging
ES6 introduced object destructuring and the spread operator, providing new ways to create objects.
// Creating variables via object destructuring
const { name, age } = { name: 'Zheng Shiyi', age: 55 };
// Merging objects using the spread operator
const defaults = { color: 'red', size: 'medium' };
const config = { ...defaults, size: 'large' };
This can be used for shallow copying objects:
const original = { a: 1, b: { c: 2 } };
const copy = { ...original };
Dynamic Property Names
ES6 allows using expressions as property names in object literals.
const dynamicKey = 'dynamicProp';
const obj = {
[dynamicKey]: 'Dynamic Property Value',
[`computed_${dynamicKey}`]: 'Computed Property Value'
};
Property Descriptors
Object.defineProperty()
allows precise control over object property behavior.
const obj = {};
Object.defineProperty(obj, 'readOnlyProp', {
value: 'Cannot Modify',
writable: false,
enumerable: true
});
Object.defineProperties(obj, {
prop1: {
value: 'Property 1',
writable: true
},
prop2: {
get() {
return this.prop1 + ' Extended';
}
}
});
Prototypal Inheritance
JavaScript uses prototypal inheritance, and there are multiple ways to set an object's prototype.
// Setting __proto__ (not recommended)
const parent = { parentProp: 'Parent Property' };
const child = { childProp: 'Child Property' };
child.__proto__ = parent;
// Using Object.setPrototypeOf
Object.setPrototypeOf(child, parent);
// Constructor inheritance
function Parent() {
this.parentProp = 'Parent Property';
}
function Child() {
Parent.call(this);
this.childProp = 'Child Property';
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn