对象创建方式
对象字面量
对象字面量是最简单直接的创建对象方式,使用花括号{}
包裹键值对。这种方式适合创建简单的、不需要复用的对象。
const person = {
name: '张三',
age: 30,
greet() {
console.log(`你好,我是${this.name}`);
}
};
对象字面量支持各种值类型作为属性值,包括函数、数组、其他对象等。ES6之后还支持计算属性名:
const propKey = 'gender';
const person = {
[propKey]: 'male',
['user' + 'Name']: '李四'
};
构造函数
使用new
关键字调用构造函数可以创建对象实例。这种方式适合需要创建多个相似对象的场景。
function Person(name, age) {
this.name = name;
this.age = age;
this.greet = function() {
console.log(`你好,我是${this.name}`);
};
}
const person1 = new Person('王五', 25);
const person2 = new Person('赵六', 28);
构造函数的问题在于每个实例都会创建自己的方法副本,造成内存浪费。解决方法是将方法定义在原型上:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.greet = function() {
console.log(`你好,我是${this.name}`);
};
Object.create()
Object.create()
方法使用现有对象作为新创建对象的原型。这种方式适合需要精确控制对象原型链的场景。
const personProto = {
greet() {
console.log(`你好,我是${this.name}`);
}
};
const person = Object.create(personProto);
person.name = '钱七';
person.age = 35;
可以传入第二个参数来定义属性描述符:
const person = Object.create(personProto, {
name: {
value: '孙八',
writable: true,
enumerable: true
},
age: {
value: 40,
enumerable: true
}
});
类语法
ES6引入了类语法,本质上是构造函数的语法糖,但提供了更清晰的面向对象编程方式。
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`你好,我是${this.name}`);
}
static createDefault() {
return new Person('默认', 0);
}
}
const person = new Person('周九', 45);
const defaultPerson = Person.createDefault();
类支持继承、静态方法、getter/setter等特性:
class Employee extends Person {
constructor(name, age, position) {
super(name, age);
this.position = position;
}
get info() {
return `${this.name}(${this.age}) - ${this.position}`;
}
}
工厂函数
工厂函数是返回对象的函数,不需要使用new
关键字。这种方式适合需要封装复杂创建逻辑的场景。
function createPerson(name, age) {
return {
name,
age,
greet() {
console.log(`你好,我是${this.name}`);
}
};
}
const person = createPerson('吴十', 50);
可以结合闭包创建私有成员:
function createPerson(name) {
let _age = 0; // 私有变量
return {
name,
get age() {
return _age;
},
set age(value) {
if(value >= 0) {
_age = value;
}
}
};
}
单例模式
单例模式确保一个类只有一个实例。在JavaScript中可以通过立即执行函数表达式(IIFE)实现。
const Singleton = (function() {
let instance;
function createInstance() {
return {
id: Math.random(),
log() {
console.log(`实例ID: ${this.id}`);
}
};
}
return {
getInstance() {
if(!instance) {
instance = createInstance();
}
return instance;
}
};
})();
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true
对象解构与合并
ES6引入的对象解构和展开运算符提供了新的对象创建方式。
// 对象解构创建变量
const { name, age } = { name: '郑十一', age: 55 };
// 展开运算符合并对象
const defaults = { color: 'red', size: 'medium' };
const config = { ...defaults, size: 'large' };
可以用于浅拷贝对象:
const original = { a: 1, b: { c: 2 } };
const copy = { ...original };
动态属性名
ES6允许在对象字面量中使用表达式作为属性名。
const dynamicKey = 'dynamicProp';
const obj = {
[dynamicKey]: '动态属性值',
[`computed_${dynamicKey}`]: '计算属性值'
};
属性描述符
通过Object.defineProperty()
可以精确控制对象属性的行为。
const obj = {};
Object.defineProperty(obj, 'readOnlyProp', {
value: '不可修改',
writable: false,
enumerable: true
});
Object.defineProperties(obj, {
prop1: {
value: '属性1',
writable: true
},
prop2: {
get() {
return this.prop1 + ' 扩展';
}
}
});
原型链继承
JavaScript使用原型链实现继承,可以通过多种方式设置对象的原型。
// 设置__proto__(不推荐)
const parent = { parentProp: '父属性' };
const child = { childProp: '子属性' };
child.__proto__ = parent;
// 使用Object.setPrototypeOf
Object.setPrototypeOf(child, parent);
// 构造函数继承
function Parent() {
this.parentProp = '父属性';
}
function Child() {
Parent.call(this);
this.childProp = '子属性';
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn