当前位置: 首页 > news >正文

Day20 JavaScript 进阶核心:IIFE、代码规范、调试与对象模型

接续上文:Day19(前端:JavaScript基础阶段)-CSDN博客

点关注不迷路哟。你的点赞、收藏,一键三连,是我持续更新的动力哟!!!

主页:一位搞嵌入式的 genius-CSDN博客

系列文章专栏:

https://blog.csdn.net/m0_73589512/category_13011829.html

目录

Day20 JavaScript 进阶核心:IIFE、代码规范、调试与对象模型

一、立即执行函数(IIFE):独立作用域的 “隔离神器”

1.1 IIFE 的基本语法与原理

形式 1:括号包裹函数表达式(推荐)

形式 2:函数表达式前加运算符(了解即可)

1.2 IIFE 的关键注意事项

(1)分号的必要性

(2)作用域隔离特性

1.3 IIFE 的经典应用场景

场景 1:解决全局变量命名冲突

场景 2:处理 DOM 事件监听的循环变量问题

二、JavaScript 代码规范:写出可维护的 “优雅代码”

2.1 基础格式规范

(1)空格与缩进

(2)分号与空行

(3)单行代码长度

2.2 命名规范

(1)变量与函数

(2)常量

2.3 模板字符串(ES6 特性)

(1)多行字符串

(2)变量插入

三、Chrome Debug 调试:定位问题的 “利器”

3.1 断点设置:让代码 “暂停” 在关键位置

方式 1:通过行号设置(可视化操作)

方式 2:通过 debugger 语句设置(代码级操作)

3.2 执行控制:分步调试代码

3.3 变量监控:实时查看数据变化

1. 查看「Scope」面板(作用域变量)

2. 查看「Watch」面板(自定义监控)

3. 通过控制台查看(临时打印)

3.4 特殊断点:应对复杂场景

1. DOM 断点:监控 DOM 元素变化

2. XHR 断点:拦截网络请求

四、JavaScript 对象:面向对象编程的基础

4.1 对象的基本概念与创建方式

(1)对象的核心特征

(2)常见创建方式

(2)修改属性

(3)添加属性

(4)删除属性

4.3 对象的遍历方式

(1)for-in 循环

(2)Object.keys() 方法

(3)for-of 直接遍历对象(不支持)

4.4 对象的内存模型:栈与堆、值类型与引用类型

(1)内存区域划分

(2)值类型与引用类型的区别

五、函数中的 this 指向:动态绑定的 “上下文”

5.1 this 的两种基础指向规则

规则 1:普通函数调用(默认绑定)

规则 2:对象方法调用(隐式绑定)

5.2 this 的开发实践价值

场景 1:简化对象方法的代码

场景 2:复用函数作为多个对象的方法

5.3 特殊注意:箭头函数没有 this

六、总结


Day20 JavaScript 进阶核心:IIFE、代码规范、调试与对象模型

在 JavaScript 学习路径中,函数的高级用法、代码规范、调试技巧与对象模型是连接基础语法与实际开发的关键桥梁。本文将围绕立即执行函数(IIFE)、代码规范、Chrome 调试工具、对象操作及 this 指向展开,结合实战场景解析核心知识点,帮助读者构建系统化的 JavaScript 进阶能力。

一、立即执行函数(IIFE):独立作用域的 “隔离神器”

立即执行函数(Immediately Invoked Function Expression,简称 IIFE)是一种特殊的函数表达式,定义后会立即执行。它的核心价值在于创建独立作用域,避免变量污染全局命名空间,是 ES6 模块普及前前端模块化的重要实现方式。

1.1 IIFE 的基本语法与原理

IIFE 的本质是 “将函数转换为表达式 + 立即调用”,核心语法有两种常见形式:

形式 1:括号包裹函数表达式(推荐)
// 基础语法:(函数表达式)()
(function() {console.log("IIFE 立即执行");
})();
​
// 带参数的 IIFE:传递参数如同普通函数
(function(name, age) {console.log(`我是${name},今年${age}岁`);
})("小明", 18); // 输出:我是小明,今年18岁
形式 2:函数表达式前加运算符(了解即可)

除了括号,+!- 等一元运算符也能将函数声明转换为表达式,进而实现立即执行:

// 逻辑非运算符转换
!function() {console.log("通过 ! 转换为表达式");
}();
​
// 加号转换
+function(score) {console.log(`分数:${score}`);
}(95); // 输出:分数:95

核心原理: JavaScript 引擎会区分 “函数声明” 和 “函数表达式”—— 仅函数表达式可以被立即调用(加 () 执行)。IIFE 通过括号或运算符,强制将函数声明转换为表达式,从而满足 “立即调用” 的语法要求。

1.2 IIFE 的关键注意事项

(1)分号的必要性

若 IIFE 前有未加分号的语句,JavaScript 可能会将其解析为函数调用,导致语法错误。例如:

// 错误示例:前一行未加分号,引擎会解析为 123(function(){})()
const num = 123
(function() {console.log("可能报错");
})();
​
// 正确示例:添加分号分隔语句
const num = 123;
(function() {console.log("正常执行");
})();
(2)作用域隔离特性

IIFE 内部声明的变量和函数,仅在 IIFE 作用域内有效,不会污染全局作用域:

(function() {// 局部变量:外部无法访问const message = "IIFE 内部变量";console.log(message); // 输出:IIFE 内部变量
})();
​
console.log(message); // 报错:ReferenceError: message is not defined

1.3 IIFE 的经典应用场景

场景 1:解决全局变量命名冲突

多人协作开发时,不同开发者可能定义同名全局变量,导致后引入的变量覆盖先引入的变量。IIFE 可将每个模块的代码包裹在独立作用域中,仅通过全局对象暴露必要接口:

// 小明开发的模块:通过 IIFE 隔离作用域
(function(window) {const moduleA = {sayHi() {console.log("小明模块:Hi!");}};// 仅暴露 moduleA 到全局window.moduleA = moduleA;
})(window);
​
// 李雷开发的模块:同样使用 IIFE
(function(window) {const moduleB = {sayHi() {console.log("李雷模块:Hello!");}};window.moduleB = moduleB;
})(window);
​
// 调用两个模块的方法,无命名冲突
moduleA.sayHi(); // 输出:小明模块:Hi!
moduleB.sayHi(); // 输出:李雷模块:Hello!

注意:ES6 普及后,import/export 已成为模块化的标准方案,但 IIFE 的作用域隔离思想仍适用于老旧项目或无模块环境的场景。

场景 2:处理 DOM 事件监听的循环变量问题

在循环中绑定事件监听时,若直接使用循环变量,可能因闭包特性导致所有事件回调共享同一变量值。IIFE 可通过参数传递,为每个循环迭代创建独立作用域:

<!-- HTML:3 个按钮 -->
<button class="btn">按钮 1</button>
<button class="btn">按钮 2</button>
<button class="btn">按钮 3</button>
​
<script>const buttons = document.querySelectorAll(".btn");// 循环绑定点击事件for (var i = 0; i < buttons.length; i++) {// IIFE 为每个 i 创建独立作用域(function(index) {buttons[index].addEventListener("click", function() {console.log(`点击了按钮 ${index + 1}`);});})(i); // 传递当前循环的 i 值}
</script>

原理var 声明的变量无块级作用域,循环结束后 i 会变成 3。IIFE 通过参数 index 捕获每次循环的 i 值,确保每个事件回调访问的是当前迭代的 index

二、JavaScript 代码规范:写出可维护的 “优雅代码”

代码规范是团队协作的 “语言共识”—— 统一的格式、命名和逻辑风格,能大幅降低代码维护成本,减少因格式问题导致的 bug。以下是前端开发中必须遵守的核心规范,部分参考 Airbnb JavaScript 规范(业界主流规范之一)。

2.1 基础格式规范

(1)空格与缩进
  • 缩进:使用 2 个空格(而非 Tab),确保不同编辑器显示一致;

  • 等号 / 运算符:等号(=)、加号(+)、减号(-)等运算符前后必须加空格;

  • 函数声明:函数名与括号之间不加空格,括号与花括号之间加 1 个空格;

  • for 循环for 关键字与括号之间加 1 个空格,分号后加 1 个空格。

// 错误示例:格式混乱
function add(a,b){return a+b;}
for(var i=0;i<5;i++){console.log(i);}
​
// 正确示例:符合规范
function add(a, b) { // 参数逗号后加空格,括号与花括号间加空格return a + b; // 运算符前后加空格
}
​
for (var i = 0; i < 5; i++) { // for 后加空格,分号后加空格console.log(i);
}
(2)分号与空行
  • 分号:每个语句结束必须加半角分号(避免 ASI 自动分号插入机制导致的意外);

  • 空行:不同逻辑块(如函数定义、条件判断)之间加 1 个空行,提升可读性。

// 正确示例:分号与空行规范
const name = "张三"; // 语句结束加分号
const age = 20;
​
// 空行分隔不同逻辑块
function greet() {console.log(`我是${name},${age}岁`);
}
​
greet();
(3)单行代码长度

单行代码长度不超过 80 个字符(部分团队放宽到 120 个),过长时需换行,换行位置优先在运算符后:

// 错误示例:单行过长
const result = 123 + 456 + 789 + 1011 + 1213 + 1415 + 1617;
​
// 正确示例:换行拆分
const result = 123 + 456 + 789 + 1011 + 1213 + 1415 + 1617;

2.2 命名规范

(1)变量与函数
  • 变量:使用小驼峰命名法(首字母小写,后续单词首字母大写),命名需体现变量含义;

  • 函数:使用小驼峰命名法,命名以动词开头(如 getUserformatDate),明确函数功能。

// 错误示例:命名模糊
const x = "2024-09-03";
function f(a) { return a * 2; }
​
// 正确示例:命名清晰
const currentDate = "2024-09-03"; // 体现“当前日期”
function doubleNumber(num) { return num * 2; } // 动词开头,明确“翻倍数字”
(2)常量

使用全大写命名法,单词间用下划线分隔(如 MAX_SIZEAPI_BASE_URL):

const MAX_AGE = 120; // 最大年龄常量
const API_BASE_URL = "https://api.example.com"; // API 基础地址常量

2.3 模板字符串(ES6 特性)

模板字符串使用反引号(`)包裹,支持多行书写变量插入,是替代传统字符串拼接的最佳方案:

(1)多行字符串

无需使用 \n 转义,直接换行即可:

// 传统字符串(繁琐)
const poem = "床前明月光,\n疑是地上霜。\n举头望明月,\n低头思故乡。";
​
// 模板字符串(简洁)
const poem = `床前明月光,
疑是地上霜。
举头望明月,
低头思故乡。`;
(2)变量插入

通过 ${变量/表达式} 语法插入值,避免字符串拼接的 + 运算符:

const name = "李白";
const age = 61;
​
// 传统拼接(易出错)
const intro = "我是" + name + ",今年" + age + "岁。";
​
// 模板字符串(清晰)
const intro = `我是${name},今年${age}岁。`;
​
// 支持表达式计算
const total = `1+2+3=${1+2+3}`; // 结果:"1+2+3=6"

三、Chrome Debug 调试:定位问题的 “利器”

Chrome 开发者工具(F12 或 Ctrl+Shift+I)的 Debug 功能,是前端开发中定位代码错误、跟踪变量变化的核心工具。掌握断点设置、变量监控和执行控制,能大幅提升问题排查效率。

3.1 断点设置:让代码 “暂停” 在关键位置

断点是调试的起点,用于让代码执行到指定行时暂停,方便观察变量状态和执行流程。常见设置方式有两种:

方式 1:通过行号设置(可视化操作)
  1. 打开 Chrome 开发者工具,切换到「Sources」面板;

  2. 在左侧文件树中找到需要调试的 JS 文件;

  3. 点击代码行号(如第 10 行),行号前会出现蓝色箭头,代表断点已设置;

  4. 刷新页面或触发代码执行(如点击按钮),代码会在断点行暂停。

方式 2:通过 debugger 语句设置(代码级操作)

在代码中插入 debugger; 语句,执行到该语句时会自动暂停,适用于需要精准定位的场景:

function calculate(a, b) {debugger; // 插入调试语句const sum = a + b;const product = a * b;return { sum, product };
}
​
calculate(3, 5); // 执行到 debugger 时暂停

3.2 执行控制:分步调试代码

代码暂停后,可通过「Sources」面板的控制按钮,分步执行代码,观察每一步的变量变化。核心按钮功能如下:

按钮图标名称(中文)功能说明
▶️继续执行从当前暂停位置继续执行,直到遇到下一个断点或代码结束
⬇️单步执行执行当前行代码,不进入函数内部(跳过函数调用)
⬇️➡️步入函数执行当前行代码,若有函数调用则进入函数内部
⬆️➡️步出函数从当前函数内部退出,回到函数调用位置
⬜️暂停执行暂停当前正在执行的代码(通常用于捕获快速执行的代码)

实战示例:调试函数执行流程

function add(a, b) {return a + b;
}
​
function calculateTotal(x, y) {const temp = add(x, y); // 断点设置在此行return temp * 2;
}
​
calculateTotal(2, 4);

  1. const temp = add(x, y); 行设置断点;

  2. 点击「步入函数」按钮,进入 add 函数内部,观察 ab 的值;

  3. 再次点击「继续执行」,回到 calculateTotal 函数,观察 temp 的值;

  4. 重复操作,直到代码执行完毕,验证结果是否符合预期。

3.3 变量监控:实时查看数据变化

调试过程中,需要实时查看变量值,常见方式有三种:

1. 查看「Scope」面板(作用域变量)

代码暂停时,「Scope」面板会显示当前作用域的变量,分为「Local」(局部变量)、「Closure」(闭包变量)、「Global」(全局变量)三类。例如:

  • 局部变量:函数内部声明的变量(如 abtemp);

  • 全局变量:window 对象下的变量(如 documentconsole)。

2. 查看「Watch」面板(自定义监控)

若需要重点关注某个变量或表达式,可在「Watch」面板添加监控:

  1. 点击「Watch」面板的「+」号;

  2. 输入变量名(如 temp)或表达式(如 temp * 2);

  3. 按下回车,面板会实时显示变量或表达式的值,变化时会高亮显示。

3. 通过控制台查看(临时打印)

代码暂停时,可在下方「Console」面板直接输入变量名(如 ab),按下回车即可查看当前值,适用于临时验证。

3.4 特殊断点:应对复杂场景

除了普通代码断点,Chrome 还支持特殊断点,用于解决 DOM 变化、网络请求等场景的调试:

1. DOM 断点:监控 DOM 元素变化

当需要跟踪某个 DOM 元素的修改(如样式变化、子元素增减)时,可设置 DOM 断点:

  1. 打开「Elements」面板,找到目标 DOM 元素;

  2. 右键点击元素,选择「Break on」→ 「Subtree modifications」(子树修改)/「Attribute modifications」(属性修改)/「Node removal」(节点删除);

  3. 当 DOM 发生对应变化时,代码会自动暂停。

2. XHR 断点:拦截网络请求

当需要调试 AJAX 请求(如接口参数、响应数据)时,可设置 XHR 断点:

  1. 在「Sources」面板,找到右侧「XHR/fetch Breakpoints」;

  2. 点击「+」号,输入接口 URL 包含的关键词(如 /api/user);

  3. 当发起包含该关键词的请求时,代码会在请求发送前暂停,方便查看请求参数。

四、JavaScript 对象:面向对象编程的基础

对象是 JavaScript 中存储复杂数据的核心结构,本质是 “键值对(key-value)的集合”。它不仅能存储数据,还能封装方法,是实现面向对象编程的基础。

4.1 对象的基本概念与创建方式

(1)对象的核心特征
  • 键(key):也称属性名,通常是字符串(可省略引号,若包含特殊字符则必须加引号);

  • 值(value):也称属性值,支持任意数据类型(数字、字符串、函数、对象等);

  • 方法:若属性值是函数,则该属性称为方法(如 obj.sayHi()),用于封装对象的行为。

(2)常见创建方式

开发中最常用的是 “对象字面量” 方式({}),语法简洁且直观:

// 基础对象:包含普通属性和方法
const person = {name: "张三", // 字符串属性age: 25,     // 数字属性isStudent: false, // 布尔属性// 方法(函数作为属性值)sayHi: function() {console.log(`你好,我是${this.name}`);},// 嵌套对象:属性值为另一个对象
address: {
city: "北京",
street: "朝阳路"
}
};// 其他创建方式(了解即可)// 1. new Object ():通过构造函数创建
const car = new Object ();
car.brand = "Tesla";
car.model = "Model 3";
// 2. Object.create ():基于原型创建
const animal = Object.create (null);
animal.type = "Dog";

### 4.2 对象的核心操作:增删改查
​
对象的操作围绕“属性”展开,核心包括**访问、修改、添加、删除**四种操作,支持两种属性访问语法:点语法(`.`)和方括号语法(`[]`)。
​
#### (1)访问属性
- **点语法**:适用于属性名符合变量命名规则(无空格、特殊字符,非数字开头),简洁常用;
- **方括号语法**:适用于属性名含特殊字符(如空格、`-`)、数字开头,或属性名存储在变量中(动态访问)。
​
```javascript
const person = {name: "李四","phone number": "13800138000", // 含空格的属性名123: "数字开头的属性"
};
​
// 1. 点语法访问
console.log(person.name); // 输出:李四
​
// 2. 方括号语法访问(特殊属性名)
console.log(person["phone number"]); // 输出:13800138000
console.log(person[123]); // 输出:数字开头的属性(数字会自动转为字符串)
​
// 3. 动态访问(属性名存储在变量中)
const key = "name";
console.log(person[key]); // 输出:李四(等价于 person["name"])
(2)修改属性

通过 “属性名赋值” 修改已有属性的值,语法与访问类似:

const person = {name: "王五",age: 30
};
​
// 修改属性值
person.age = 31; // 点语法修改
person["name"] = "王五六"; // 方括号语法修改
​
console.log(person.age); // 输出:31
console.log(person.name); // 输出:王五六
(3)添加属性

JavaScript 对象支持动态添加属性 —— 直接对不存在的属性赋值即可:

const person = {name: "赵六"
};
​
// 添加普通属性
person.gender = "男";
// 添加方法
person.introduce = function() {console.log(`我是${this.name},性别${this.gender}`);
};
​
console.log(person.gender); // 输出:男
person.introduce(); // 输出:我是赵六,性别男
(4)删除属性

通过 delete 关键字删除对象的属性,删除后属性会从对象中移除(区别于赋值为 undefined):

const person = {name: "孙七",age: 28,hobby: "篮球"
};
​
// 删除 age 属性
delete person.age;
// 删除 hobby 属性
delete person["hobby"];
​
console.log(person.age); // 输出:undefined(属性已删除)
console.log("age" in person); // 输出:false(检查属性是否存在)

4.3 对象的遍历方式

当需要批量处理对象的属性时,需通过遍历实现。JavaScript 提供多种对象遍历方法,核心常用的有 for-in 循环和 Object.keys() 方法。

(1)for-in 循环

for-in 循环会遍历对象的所有可枚举属性(包括继承的属性),语法如下:

const person = {name: "周八",age: 22,gender: "女"
};
​
// for-in 遍历对象
for (const key in person) {// 可选:过滤继承的属性(仅遍历自身属性)if (person.hasOwnProperty(key)) {const value = person[key]; // 注意:此处需用方括号语法console.log(`${key}: ${value}`);}
}
// 输出:
// name: 周八
// age: 22
// gender: 女

注意for-in 遍历顺序不固定(尤其是数字属性会优先按升序排列),且会遍历继承属性,因此建议用 hasOwnProperty(key) 过滤自身属性。

(2)Object.keys() 方法

Object.keys(obj) 会返回对象自身所有可枚举属性的数组,再结合 for-offorEach 循环遍历,是更现代的遍历方式:

const person = {name: "吴九",age: 35,job: "工程师"
};
​
// 1. 获取属性名数组
const keys = Object.keys(person);
console.log(keys); // 输出:["name", "age", "job"]
​
// 2. for-of 遍历
for (const key of keys) {console.log(`${key}: ${person[key]}`);
}
​
// 3. forEach 遍历
keys.forEach(key => {console.log(`${key}: ${person[key]}`);
});
(3)for-of 直接遍历对象(不支持)

需注意:for-of 循环默认不支持遍历普通对象(仅支持数组、字符串等 “可迭代对象”),直接使用会报错:

const person = { name: "郑十" };
for (const value of person) {console.log(value); // 报错:TypeError: person is not iterable
}

若需用 for-of 遍历对象,需先通过 Object.values()Object.entries() 转换为可迭代对象:

// Object.values():获取属性值数组
for (const value of Object.values(person)) {console.log(value); // 输出:郑十
}
​
// Object.entries():获取 [key, value] 数组
for (const [key, value] of Object.entries(person)) {console.log(`${key}: ${value}`); // 输出:name: 郑十
}

4.4 对象的内存模型:栈与堆、值类型与引用类型

理解对象的内存存储机制,是解决 “对象赋值后修改同步” 等问题的关键。JavaScript 内存分为栈内存堆内存,不同类型的数据存储方式不同。

(1)内存区域划分
  • 栈内存:存储值类型(原始类型) 数据(如 NumberStringBooleanundefinednullSymbol),特点是容量小、访问速度快,数据直接存储在栈中;

  • 堆内存:存储引用类型数据(如 ObjectArrayFunction),特点是容量大、可动态分配,数据存储在堆中,栈中仅保存指向堆内存的 “引用地址”(类似指针)。

(2)值类型与引用类型的区别
类型分类包含类型存储位置赋值行为示例
值类型Number、String 等栈内存赋值的是值的副本,修改互不影响let a = 10; let b = a; b = 20;(a 仍为 10)
引用类型Object、Array 等堆内存(栈存引用)赋值的是引用地址,修改共享对象let obj1 = {x:1}; let obj2 = obj1; obj2.x=2;(obj1.x 变为 2)

实战示例:验证引用类型的共享特性

// 1. 值类型赋值:独立副本
let num1 = 5;
let num2 = num1;
num2 = 10;
console.log(num1); // 输出:5(num1 不受影响)
​
// 2. 引用类型赋值:共享引用
const obj1 = { name: "A" };
const obj2 = obj1; // obj2 保存的是 obj1 的引用地址
obj2.name = "B"; // 修改共享对象的属性
console.log(obj1.name); // 输出:B(obj1 也被修改)
​
// 3. 函数参数传递(同赋值规则)
function changeValue(num, obj) {num = 100; // 值类型参数:修改副本,不影响外部obj.age = 20; // 引用类型参数:修改共享对象,影响外部
}
​
let x = 10;
const user = { age: 18 };
changeValue(x, user);
console.log(x); // 输出:10(无变化)
console.log(user.age); // 输出:20(被修改)

五、函数中的 this 指向:动态绑定的 “上下文”

this 是 JavaScript 函数中的特殊变量,代表 “函数的执行上下文”(即函数被谁调用)。它的指向并非固定,而是由函数的调用方式决定,这是理解 this 的核心。

5.1 this 的两种基础指向规则

规则 1:普通函数调用(默认绑定)

当函数独立调用(不依附于任何对象)时,非严格模式下 this 指向全局对象(浏览器中为 window,Node.js 中为 global);严格模式下 thisundefined

// 非严格模式(默认)
function sayGlobal() {console.log(this === window); // 输出:true
}
sayGlobal(); // 普通函数调用,this 指向 window
​
// 严格模式
function sayStrict() {"use strict"; // 启用严格模式console.log(this); // 输出:undefined
}
sayStrict(); // 普通函数调用,this 为 undefined
​
// 注意:对象方法赋值后独立调用,仍属于普通调用
const obj = {fn: function() {console.log(this === window);}
};
const independentFn = obj.fn;
independentFn(); // 输出:true(this 指向 window,非 obj)
规则 2:对象方法调用(隐式绑定)

当函数作为对象的方法调用时(如 obj.fn()),this 指向调用该方法的对象(即 obj)。这是开发中最常见的 this 指向场景。

const user = {name: "小明",age: 18,introduce: function() {// this 指向调用 introduce 方法的对象(user)console.log(`我是${this.name},今年${this.age}岁`);},address: {city: "上海",showCity: function() {// this 指向调用 showCity 方法的对象(address)console.log(`我在${this.city}`);}}
};
​
user.introduce(); // 输出:我是小明,今年18岁(this 指向 user)
user.address.showCity(); // 输出:我在上海(this 指向 address)

5.2 this 的开发实践价值

this 的核心价值在于动态绑定调用者,避免因对象变量名变更导致的代码修改,提升函数的复用性。

场景 1:简化对象方法的代码

若不使用 this,方法需硬编码对象名,当对象名变更时,所有方法都需修改:

// 无 this:硬编码对象名,灵活性差
const user1 = {name: "小红",introduce: function() {console.log(`我是${user1.name}`); // 硬编码 user1}
};
​
// 有 this:动态绑定,灵活性高
const user2 = {name: "小红",introduce: function() {console.log(`我是${this.name}`); // 无需关心对象名}
};
​
// 对象名变更时,无 this 的代码需修改,有 this 的代码无需修改
const newUser = user2;
newUser.introduce(); // 输出:我是小红(this 自动指向 newUser)
场景 2:复用函数作为多个对象的方法

同一函数可作为多个对象的方法,this 会自动指向当前调用对象:

// 定义通用的 introduce 函数
function introduce() {console.log(`我是${this.name},职业是${this.job}`);
}
​
// 多个对象复用该函数
const teacher = {name: "张老师",job: "教师",introduce: introduce // 赋值函数作为方法
};
​
const doctor = {name: "李医生",job: "医生",introduce: introduce // 复用同一函数
};
​
teacher.introduce(); // 输出:我是张老师,职业是教师(this 指向 teacher)
doctor.introduce(); // 输出:我是李医生,职业是医生(this 指向 doctor)

5.3 特殊注意:箭头函数没有 this

箭头函数是 ES6 新增的函数形式,它没有自己的 this,而是继承外层作用域的 this。这是箭头函数与普通函数的核心区别之一,需特别注意。

const obj = {name: "箭头函数测试",// 普通函数:this 指向 objnormalFn: function() {console.log(this.name); // 输出:箭头函数测试},// 箭头函数:无自己的 this,继承外层 this(此处外层是全局作用域,this 指向 window)arrowFn: () => {console.log(this.name); // 输出:undefined(window 无 name 属性)}
};
​
obj.normalFn(); // 正常输出
obj.arrowFn(); // 输出 undefined

开发建议

  • 定义对象方法时,优先使用普通函数(确保 this 指向对象);

  • 定义回调函数(如 setTimeout、数组方法回调)时,可使用箭头函数(继承外层 this,避免绑定问题)。

六、总结

本文围绕 JavaScript 进阶核心知识点展开,从 IIFE 的作用域隔离、代码规范的工程价值,到 Chrome Debug 的实战技巧,再到对象的操作与内存模型、this 的动态指向,覆盖了前端开发中高频使用的技术点。

核心要点回顾:

  1. IIFE:通过独立作用域解决全局变量污染,是模块化的早期方案;

  2. 代码规范:统一格式、命名和逻辑,提升代码可维护性,是团队协作的基础;

  3. Chrome Debug:断点设置、分步执行和变量监控,是定位问题的核心工具;

  4. 对象模型:键值对存储、栈堆内存差异、值类型与引用类型的赋值规则,是理解数据存储的关键;

  5. this 指向:由函数调用方式决定,普通调用指向全局,对象方法调用指向对象,箭头函数无自身 this

这些知识点不仅是面试高频考点,更是实际开发中解决问题的基础。建议结合代码练习(如封装工具函数、调试实际项目),逐步深化理解,将理论转化为实战能力。

http://www.dtcms.com/a/364898.html

相关文章:

  • AI优化SEO关键词策略指南
  • 时序数据库选型指南:Apache IoTDB快速部署与实战应用
  • 时序数据库IoTDB的核心优势
  • mysql第五天学习 Mysql全局优化总结
  • 如何使文件夹内的软件或者文件不受windows 安全中心的监视
  • FastGPT社区版大语言模型知识库、Agent开源项目推荐
  • 智慧用电安全解决方案:打造全流程可视化管控
  • 知微集:Python中的线程Thread(一)
  • MCP是什么? 小白如何学习使用MCP?一篇文档带你详细了解神秘的MCP
  • 【C++】控制台输入与输出
  • osgb转b3dm转glb小工具流程-解决办法
  • Linux内核进程管理子系统有什么第四十一回 —— 进程主结构详解(37)
  • 《用 Flask 构建用户认证系统:从零开始实现注册与登录功能》
  • 10.2 工程学中的矩阵(2)
  • 基于Docker和Kubernetes的CI/CD流水线架构设计与优化实践
  • 加解密安全-侧信道攻击
  • AI Waifu RAT:新型恶意软件伪装AI助手劫持用户电脑
  • OpenLayers常用控件 -- 章节一:地图缩放控件详解教程
  • Java 反序列化漏洞
  • 专题四_前缀和_一维前缀和
  • JAVA 十二幕啦啦啦啦啦啦啦啊啦啦啦啦a
  • AI IDE+AI 辅助编程,真能让程序员 “告别 996” 吗?
  • 【Java】对于XML文档读取和增删改查操作与JDBC编程的读取和增删改查操作的有感而发
  • 面试题:JVM与G1要点总结
  • 告别 Hadoop,拥抱 StarRocks!政采云数据平台升级之路
  • 海思HI3516CV610-20S,HI3516CV610专为安防市场超高清智慧视觉SoC硬件设计的一款开发板
  • MongoDB 聚合查询超时:索引优化与分片策略的踩坑记录
  • Prometheus监控预警系统深度解析:架构、优劣、成本与竞品
  • CryptMsgGetParam函数分析之CMSG_INNER_CONTENT_TYPE_PARAM
  • 110个作品涨粉210万!用Coze智能体工作流1分钟生成爆款名著金句视频,无需剪辑,附详细教程