JavaScript对象万能解答公式,一应俱全!!!

174 阅读7分钟
 
# JavaScript 对象全面解析

## 目录
1. [对象创建方式](#对象创建方式)
2. [创建方式对比](#创建方式对比)
3. [对象原理](#对象原理)
4. [Getter/Setter](#gettersetter)
5. [对象自带方法](#对象自带方法)
6. [常用方法对比](#常用方法对比)
7. [总结](#总结)

---

对象创建方式

1. 对象字面量

 
const obj = { 
  name'John',
  age30
};

2. new Object()

 
const obj = new Object();
obj.name = 'John';

3. 构造函数

 
function Person(name) {
  this.name = name;
}
const john = new Person('John');

4. Object.create()

 
const protoObj = { x10 };
const newObj = Object.create(protoObj);

5. ES6 Class

 
class Person {
  constructor(name) {
    this.name = name;
  }
}
const john = new Person('John');

6. 工厂函数

 
function createPerson(name) {
  return {
    name,
    greet() {
      console.log(`Hello ${this.name}`);
    }
  };
}

创建方式对比

方式原型链内存效率私有属性支持适用场景
对象字面量Object.prototype简单数据存储
new Object()Object.prototype不推荐使用
构造函数自定义原型需要多个相似实例
Object.create指定原型原型继承场景
ES6 Class自定义原型✔️(通过WeakMap)面向对象编程
工厂函数Object.prototype✔️(闭包)需要封装私有属性

对象原理

核心特性

  1. 原型链机制:通过 __proto__ 实现继承链

  2. 属性描述符

     
    Object.getOwnPropertyDescriptor(obj, 'prop')
    
    • configurable
    • enumerable
    • writable
    • value

configurable

configurable 属性是一个布尔值,表示该属性是否可以被配置。如果 configurable 为 false,则该属性的描述符(除了 value 和 writable)不能被修改,且该属性不能被删除。

 
let obj = {};
Object.defineProperty(obj, 'name', {
  value'张三',
  configurablefalse
});

// 尝试修改属性描述符
Object.defineProperty(obj, 'name', {
  value'李四'
}); // 抛出错误,因为 configurable 为 false

// 尝试删除属性
delete obj.name// 返回 false,因为 configurable 为 false

enumerable

enumerable 属性是一个布尔值,表示该属性是否可以在枚举操作(如 for...in 循环或 Object.keys())中被枚举。

 
let obj = {
  name'张三',
  age25
};

Object.defineProperty(obj, 'email', {
  value'zhangsan@example.com',
  enumerablefalse
});

for (let key in obj) {
  console.log(key); // 输出:name, age
}

console.log(Object.keys(obj)); // 输出:['name', 'age']

writable

writable 属性是一个布尔值,表示该属性的值是否可以被修改。如果 writable 为 false,则该属性的值不能被修改。

 
let obj = {};
Object.defineProperty(obj, 'name', {
  value'张三',
  writablefalse
});

obj.name = '李四'// 不会修改,因为 writable 为 false
console.log(obj.name); // 输出:张三

value

value 属性是该属性的值。对于数据属性,value 是实际存储的值;对于访问器属性,value 通常不适用。

 
let obj = {};
Object.defineProperty(obj, 'name', {
  value'张三'
});

console.log(obj.name); // 输出:张三

定义属性描述符

 
let obj = {};
Object.defineProperty(obj, 'name', {
  value'张三',
  writablefalse,
  enumerabletrue,
  configurablefalse
});

console.log(obj.name); // 输出:张三
obj.name = '李四'// 不会修改,因为 writable 为 false
console.log(obj.name); // 输出:张三

for (let key in obj) {
  console.log(key); // 输出:name
}

delete obj.name// 返回 false,因为 configurable 为 false

3. this绑定:动态绑定,取决于调用方式(下面会挨个举例说明)

内存分配

  • 基本类型:栈内存存储
  • 引用类型:堆内存存储,栈存指针

Getter/Setter

定义方式

 
const obj = {
  _value0,
  get count() {
    return this._value;
  },
  set count(val) {
    this._value = val > 0 ? val : 0;
  }
};

特性对比

特性GetterSetter
触发时机访问属性时设置属性时
返回值必须有返回值无要求
参数无参数接收赋值参数
主要用途计算属性/访问控制数据验证/副作用触发

对象自带方法

核心方法列表

方法作用描述返回值是否修改原对象
Object.assign(target, ...sources)合并对象属性目标对象✔️
Object.keys(obj)获取可枚举属性键名数组Array
Object.values(obj)获取可枚举属性值数组Array
Object.entries(obj)获取键值对数组Array
Object.defineProperty()定义/修改属性特性修改后的对象✔️
Object.freeze()冻结对象(不可修改)冻结对象✔️
Object.seal()密封对象(不能增删属性)密封对象✔️
Object.create(proto)创建指定原型的对象新对象
Object.hasOwnProperty()检查是否自有属性Boolean
Object.is()增强型相等比较Boolean

常用方法示例

 
// 合并对象
const merged = Object.assign({}, {a:1}, {b:2}); // {a:1, b:2}

// 获取键值对
Object.entries({a:1b:2}); // [['a',1], ['b',2]]

// 属性定义
Object.defineProperty(obj, 'prop', {
  value42,
  writablefalse
});

常用方法对比

Object.assign vs 扩展运算符

特性Object.assign...扩展运算符
原型链属性不复制不复制
嵌套对象浅拷贝浅拷贝
数组合并不可用支持
性能较好更优

in操作符 vs hasOwnProperty

特性in操作符hasOwnProperty
检测范围原型链+自有仅自有属性
符号属性支持支持
安全调用需要try-catch直接调用

选择创建方式的建议

  1. 简单配置 ➔ 对象字面量
  2. 需要继承 ➔ Object.create()
  3. 类体系 ➔ ES6 Class
  4. 私有属性 ➔ 工厂函数 + 闭包

方法使用指南

  • 数据合并:优先使用扩展运算符 ...
  • 属性遍历:Object.entries() + 解构
  • 属性保护:Object.freeze() 用于常量对象
  • 精确比较:Object.is(NaN, NaN) → true

最佳实践:优先使用ES6+语法,合理选择对象创建方式,注意深浅拷贝的区别

 
# JavaScript 中 `this` 绑定的所有场景详解

## 目录
1. [全局上下文](#全局上下文)
2. [函数调用](#函数调用)
3. [对象方法](#对象方法)
4. [构造函数](#构造函数)
5. [箭头函数](#箭头函数)
6. [事件处理函数](#事件处理函数)
7. [call/apply/bind](#callapplybind)
8. [回调函数](#回调函数)
9. [模块作用域](#模块作用域)
10. [类中的 this](#类中的-this)
11. [严格模式](#严格模式)
12. [总结与最佳实践](#总结与最佳实践)

---

## 全局上下文
```javascript
console.log(this); // 浏览器中指向 window 对象 | Node.js 中指向 global 对象

函数调用

普通函数

 
function showThis() {
  console.log(this); // 非严格模式:window/global | 严格模式:undefined
}
showThis();

嵌套函数

 
const obj = {
  method() {
    function inner() {
      console.log(this); // 非严格模式:window/global | 严格模式:undefined
    }
    inner();
  }
};
obj.method();

对象方法

 
const obj = {
  name'Object',
  logName() {
    console.log(this.name); // 指向 obj 对象
  }
};
obj.logName(); // "Object"

// 方法赋值给变量
const fn = obj.logName;
fn(); // 非严格模式:undefined(丢失 this 绑定)

构造函数

 
function Person(name) {
  this.name = name; // this 指向新创建的实例
}
const john = new Person('John');

箭头函数

 
const obj = {
  name'Obj',
  logName() => {
    console.log(this.name); // 指向外层作用域的 this(此处为 window/global)
  }
};
obj.logName(); // undefined(若全局没有 name 属性)

const outerThis = this;
const arrowFn = () => {
  console.log(this === outerThis); // true(永远捕获定义时的 this)
};

事件处理函数

 
button.addEventListener('click'function() {
  console.log(this); // 指向触发事件的元素(button)
});

// 使用箭头函数
button.addEventListener('click'() => {
  console.log(this); // 指向定义时的外层 this(可能是 window)
});

call/apply/bind

 
function showThis() {
  console.log(this.value);
}

const ctx = { value42 };

showThis.call(ctx);    // 42
showThis.apply(ctx);   // 42
const boundFn = showThis.bind(ctx);
boundFn();             // 42

回调函数

 
const obj = {
  data'Hello',
  handleData() {
    setTimeout(function() {
      console.log(this.data); // 非严格模式:undefined(this 指向 window)
    }, 100);
  }
};
obj.handleData();

// 解决方案
// 1. 使用箭头函数
setTimeout(() => console.log(this.data), 100); // 捕获外层 this
// 2. 保存 this
const self = this;
setTimeout(function() { console.log(self.data) }, 100);
// 3. 使用 bind
setTimeout(function() { console.log(this.data) }.bind(this), 100);

模块作用域

 
// ES6 模块中顶层 this 指向 undefined(严格模式)
console.log(this); // undefined

类中的 this

 
class Person {
  constructor(name) {
    this.name = name; // 指向实例
  }

  logName() {
    console.log(this.name);
  }

  // 箭头函数方法
  arrowLogName = () => {
    console.log(this.name); // 始终绑定实例
  };
}

const p = new Person('John');
const fn = p.logName;
fn(); // 错误:this 为 undefined(严格模式)
const arrowFn = p.arrowLogName;
arrowFn(); // 正确:"John"

严格模式

 
"use strict";
function test() {
  console.log(this); // undefined
}
test();

总结与最佳实践

this 绑定优先级(从高到低)

  1. new 绑定:new Constructor()
  2. 显式绑定:call/apply/bind
  3. 隐式绑定:obj.method()
  4. 默认绑定:全局对象或 undefined(严格模式)

避坑指南

  • 回调函数中的 this 丢失:使用箭头函数或 bind
  • 避免在对象方法中使用箭头函数(除非需要绑定外层 this
  • 类方法推荐使用普通函数,需要绑定实例时使用箭头函数属性
  • 严格模式下函数调用的 this 为 undefined

最佳实践

 
// 安全的对象方法定义
const obj = {
  data'value',
  handler() { /* 使用 this */ }
};

// 需要绑定实例时
class MyClass {
  handler = () => {
    console.log(this); // 始终指向实例
  };
}

// 回调函数处理
button.addEventListener('click'this.handleClick.bind(this));
// 或
button.addEventListener('click'() => this.handleClick());

总结

JavaScript对象是JavaScript学习中重要的一环,和JavaScript数组一样方法诸多需要好好梳理和练习理解的,如弱缺失欢迎广大前端小伙伴建议和补充。每个人观点和出发点不一样但是要到达的终点却是一样的!!!如果想持续不断坚持学习前端知识也可以关注我**公众号:【鱼樱AI实验室】**学习更多的前端知识从0-1梳理总结。。。持续免费分享哦!!!拿来即用即练!!!