阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 对象基础

对象基础

作者:陈川 阅读数:17408人阅读 分类: JavaScript

JavaScript中的对象是一种复合数据类型,用于存储键值对的集合。它不仅是语言的核心概念,还提供了灵活的数据组织和操作方式。理解对象的基础特性对编写高效代码至关重要。

对象的基本结构

对象由属性和方法构成,属性是键值对,键通常是字符串或Symbol类型,值可以是任意数据类型。方法则是函数类型的属性。对象字面量是最常见的创建方式:

const person = {
  name: '张三',
  age: 30,
  greet: function() {
    console.log(`你好,我是${this.name}`);
  }
};

通过点表示法或方括号可以访问属性:

console.log(person.name); // "张三"
console.log(person['age']); // 30
person.greet(); // 调用方法

动态属性操作

JavaScript允许运行时动态添加或删除属性:

// 添加新属性
person.job = '工程师';
// 删除属性
delete person.age;
// 检查属性存在性
'name' in person; // true

使用Object.keys()可获取所有可枚举属性:

const keys = Object.keys(person); // ["name", "greet", "job"]

构造函数与实例

通过构造函数可以创建多个相似对象:

function Book(title, author) {
  this.title = title;
  this.author = author;
  this.getInfo = function() {
    return `${this.title} - ${this.author}`;
  };
}

const book1 = new Book('JavaScript高级编程', 'Nicholas');
console.log(book1.getInfo());

原型继承机制

每个JavaScript对象都有原型链,用于实现继承:

Book.prototype.discount = function(percent) {
  return `本书享受${percent}%折扣`;
};
console.log(book1.discount(20)); // 调用原型方法

使用Object.create()可显式设置原型:

const animal = { eats: true };
const rabbit = Object.create(animal);
console.log(rabbit.eats); // true

对象解构赋值

ES6引入的解构语法简化了对象属性提取:

const { name, job } = person;
console.log(name, job); // "张三" "工程师"

// 嵌套解构
const user = {
  id: 1,
  profile: {
    name: '李四',
    address: '北京'
  }
};
const { profile: { address } } = user;
console.log(address); // "北京"

对象属性描述符

通过属性描述符可以控制属性行为:

Object.defineProperty(person, 'gender', {
  value: 'male',
  writable: false,  // 不可写
  enumerable: true  // 可枚举
});

// 尝试修改会静默失败(严格模式会报错)
person.gender = 'female';
console.log(person.gender); // 仍为"male"

获取完整描述符:

const desc = Object.getOwnPropertyDescriptor(person, 'name');
/*
{
  value: "张三",
  writable: true,
  enumerable: true,
  configurable: true
}
*/

对象冻结与密封

JavaScript提供了三种限制对象修改的方式:

const obj = { prop: 42 };

// 1. 防止扩展
Object.preventExtensions(obj);
obj.newProp = 'test'; // 静默失败

// 2. 密封对象(不能添加/删除属性)
Object.seal(obj);
delete obj.prop; // 静默失败

// 3. 冻结对象(完全不可变)
Object.freeze(obj);
obj.prop = 999; // 静默失败

ES6类语法糖

class语法提供了更清晰的面向对象写法:

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }

  // Getter方法
  get area() {
    return this.calcArea();
  }

  // 实例方法
  calcArea() {
    return this.height * this.width;
  }

  // 静态方法
  static createSquare(side) {
    return new Rectangle(side, side);
  }
}

const rect = new Rectangle(10, 5);
console.log(rect.area); // 50
const square = Rectangle.createSquare(10);

对象迭代方式

ES6新增了多种对象迭代方法:

const scores = { math: 90, science: 85, history: 88 };

// 1. Object.keys()
for (const key of Object.keys(scores)) {
  console.log(key);
}

// 2. Object.values()
console.log(Object.values(scores)); // [90, 85, 88]

// 3. Object.entries()
for (const [subject, score] of Object.entries(scores)) {
  console.log(`${subject}: ${score}`);
}

深拷贝与浅拷贝

对象复制需要特别注意引用问题:

// 浅拷贝
const original = { a: 1, b: { c: 2 } };
const shallowCopy = Object.assign({}, original);
shallowCopy.b.c = 99;
console.log(original.b.c); // 99 (被修改)

// 深拷贝方案
const deepCopy = JSON.parse(JSON.stringify(original));
deepCopy.b.c = 100;
console.log(original.b.c); // 仍为99

对象与Map比较

ES6的Map在某些场景比对象更适合:

const map = new Map();
map.set('name', '王五');
map.set(1, '数字键');
map.set({}, '对象作为键');

console.log(map.get(1)); // "数字键"
console.log(map.size); // 3

// 对象键不会被转为字符串
const objKey = {};
map.set(objKey, '特殊对象');
console.log(map.get({})); // undefined (不同引用)
console.log(map.get(objKey)); // "特殊对象"

可选链操作符

ES2020引入的可选链简化了深层属性访问:

const company = {
  name: 'TechCorp',
  departments: {
    dev: { size: 50 },
    hr: { size: 10 }
  }
};

// 传统方式
const devSize = company.departments && company.departments.dev && company.departments.dev.size;

// 可选链方式
const modernDevSize = company.departments?.dev?.size;
console.log(modernDevSize); // 50

// 不存在的属性返回undefined
const salesSize = company.departments?.sales?.size;
console.log(salesSize); // undefined

空值合并运算符

与可选链配合使用的逻辑运算符:

const config = {
  timeout: 0,
  title: '',
  animation: null
};

// 传统默认值设置
const timeout = config.timeout !== undefined ? config.timeout : 1000;

// 空值合并运算符
const modernTimeout = config.timeout ?? 1000;
const title = config.title ?? '默认标题';
const animation = config.animation ?? 'fade';

console.log(modernTimeout); // 0 (0不是null/undefined)
console.log(title); // "" (空字符串不是null/undefined)
console.log(animation); // "fade"

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:属性描述符

下一篇:数组基础

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌