切换导航
简历
工具
演示
查询
导航菜单
服务端
30
前端
114
数据库
82
进阶开发
8
桌面程序
2
QA
15
软件使用
36
规范协议
5
操作系统
11
AI
0
复用资源
6
硬件
0
标签
HTML
正则表达式
Json
包管理工具
vite
CSS
XPath
JavaScript
Jquery
less
ES6
Vue
React
vue 3
Layui
editor.md
sea.js
Zepto.js
mysql.js
mssql.js
NodeJs
Express
前端template
YAML
杂项
外部链接
.NET Core SDK和运行时安装包
淘宝 NPM 镜像
查询网
Tables Generator线上表格转换工具
引用cdn在线脚本和样式
首页
前端
JavaScript 中关键字 self 的作用和使用
[TOC] 在 JavaScript 中,`self` **并不是语言层面的关键字**,而是一个在特定环境中存在的**全局属性**,同时也是开发者常用的一种**编程模式**(用于保存 `this` 的引用)。下面将从这两个角度详细说明其作用、使用方式、优势及缺陷。 --- ## 一、`self` 作为全局对象 ### 1. 作用与背景 - **在 Web Workers / Service Workers 中**:`self` 是**全局对象本身**,类似于主线程中的 `window`。可以通过 `self` 访问 Worker 的全局函数(如 `postMessage`、`onmessage`)和变量。 - **在浏览器主线程中**:`self` 是 `window` 对象的一个属性,且 `window.self` 指向 `window` 自身(即 `self === window`)。因此,在主线程中使用 `self` 等价于使用 `window`。 - **在其他 JavaScript 环境**(如 Node.js):`self` 通常不存在,除非环境模拟了 Web API。现代 JavaScript 推荐使用 `globalThis` 作为跨环境的统一全局对象。 ### 2. 使用示例 #### 在 Web Worker 中 ```javascript // worker.js self.onmessage = function(e) { console.log('Worker received:', e.data); self.postMessage('Hello from worker'); }; ``` 这里 `self` 就是 Worker 的全局作用域。 #### 在浏览器主线程中 ```javascript // 主线程 console.log(self === window); // true self.setTimeout(() => { console.log('Hello from self.setTimeout'); }, 1000); ``` 由于 `self` 就是 `window`,所以可以直接使用 `self` 代替 `window` 调用全局 API。 #### 跨环境代码(同时兼容主线程和 Worker) ```javascript if (typeof self !== 'undefined' && self.postMessage) { // 当前在 Worker 环境 self.postMessage('Worker code'); } else { // 当前在主线程 window.postMessage('Main thread code', '*'); } ``` ### 3. 优势 - **环境无关性**:编写同时运行在主线程和 Worker 中的代码时,使用 `self` 可以避免直接依赖 `window`(Worker 中没有 `window`),提高代码的可移植性。 - **语义清晰**:在 Worker 代码中,`self` 明确表示“全局对象自身”,有助于代码理解。 ### 4. 缺陷 - **可被覆盖**:在浏览器中,`self` 只是一个普通的全局属性,可以被重新赋值。例如 `self = null;` 会导致后续使用出错。 - **并非标准 ECMAScript**:`self` 不属于 ECMAScript 规范,而是 Web API 的一部分。在 Node.js 等非浏览器环境中不可用,因此依赖 `self` 的代码无法直接在这些环境中运行。 - **模块作用域**:在 ES 模块中,顶层的 `self` 仍然指向全局对象,但模块内部的变量不会污染全局,因此 `self` 依然可用,但需注意模块中 `this` 是 `undefined`,而 `self` 始终指向全局。 --- ## 二、`self` 作为保存 `this` 的变量(编程模式) ### 1. 作用与背景 在 JavaScript 中,函数的 `this` 由调用方式决定(动态绑定),在嵌套函数或回调函数中很容易丢失外部 `this` 的引用。为了解决这个问题,开发者常在外层将 `this` 赋值给一个变量(通常命名为 `self` 或 `that`),然后在内部函数中使用这个变量。 ### 2. 使用示例 ```javascript function Person(name) { this.name = name; var self = this; // 保存 this 引用 setTimeout(function() { // 这里的 this 指向全局对象(或 undefined 在严格模式下) console.log('Hello, ' + self.name); // 使用 self 访问正确的 name }, 1000); } const p = new Person('Alice'); ``` 如果不使用 `self`,内部函数中的 `this.name` 将是 `undefined`。 ### 3. 优势 - **简单直观**:易于理解和实现,无需学习新的语法。 - **兼容性好**:在 ES6 箭头函数出现之前,这是最常用的解决方案,适用于所有 JavaScript 环境。 ### 4. 缺陷 - **需要手动管理**:必须记得在每处需要的地方声明 `self = this`,容易遗漏或命名不一致。 - **命名冲突**:如果作用域内已经有一个名为 `self` 的变量,就会发生覆盖或混淆。 - **冗余代码**:在箭头函数普及后,这种方式显得冗余。箭头函数会捕获定义时的 `this`(词法作用域),不再需要 `self`。 ```javascript function Person(name) { this.name = name; setTimeout(() => { console.log('Hello, ' + this.name); // 箭头函数中的 this 来自外层 }, 1000); } ``` - **潜在的性能影响**:虽然微乎其微,但保存闭包变量会增加一点内存占用。 --- ## 总结 | 用法 | 本质 | 使用场景 | 现代替代方案 | |------|------|----------|--------------| | `self` 全局属性 | Web API 提供的全局对象 | Worker 环境、跨环境代码 | `globalThis`(统一全局对象) | | `self` 保存 `this` | 编程模式(变量命名) | 需要在内层函数访问外层 `this` | 箭头函数、`.bind()` | **建议**: - 在 Worker 代码中,可以使用 `self` 访问全局对象,但若需跨环境,建议使用 `globalThis`(ES2020 引入)。 - 在需要保存 `this` 的场景,优先使用**箭头函数**代替 `self` 变量,代码更简洁且不易出错。 - 如果必须兼容老旧环境(如 IE),使用 `var self = this;` 仍然是可靠的做法,但注意避免命名冲突。
扫一扫手机看
点击排行
windows 文件资源管理器使用
Layui 弹窗open使用说明
SQL Server 中字符串函数使用
C# 使用QQ邮箱代理做邮件接收功能
SQL Server关于apply的两种形式cross apply 和 outer apply
ASP.NET MVC 模型的自定义验证
nvm安装及常用命令
SQL Server 中数据类型转换
SQL Server 中WITH AS短语的使用
IE浏览器下AJAX缓存问题导致数据不更新的解决办法
订阅号