{"id":20355695,"url":"https://github.com/geekeast/deep-javascript-v3","last_synced_at":"2025-04-12T02:50:54.990Z","repository":{"id":42849365,"uuid":"222176408","full_name":"GeekEast/Deep-Javascript-v3","owner":"GeekEast","description":"Course Notes for Deep Javascript v3 from Kyle Simpson","archived":false,"fork":false,"pushed_at":"2023-03-04T16:41:25.000Z","size":45946,"stargazers_count":6,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-03T23:34:34.007Z","etag":null,"topics":["closure","coercion","prototype","scope","types"],"latest_commit_sha":null,"homepage":"https://frontendmasters.com/courses/deep-javascript-v3/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GeekEast.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-11-17T00:22:01.000Z","updated_at":"2022-01-09T10:04:20.000Z","dependencies_parsed_at":"2022-08-22T10:50:19.488Z","dependency_job_id":null,"html_url":"https://github.com/GeekEast/Deep-Javascript-v3","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeekEast%2FDeep-Javascript-v3","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeekEast%2FDeep-Javascript-v3/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeekEast%2FDeep-Javascript-v3/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeekEast%2FDeep-Javascript-v3/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GeekEast","download_url":"https://codeload.github.com/GeekEast/Deep-Javascript-v3/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248509202,"owners_count":21115962,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["closure","coercion","prototype","scope","types"],"created_at":"2024-11-14T23:13:47.827Z","updated_at":"2025-04-12T02:50:54.967Z","avatar_url":"https://github.com/GeekEast.png","language":"JavaScript","readme":"\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n## Table Of Content\n\n- [v8引擎基本原理](#v8%E5%BC%95%E6%93%8E%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86)\n  - [编程语言类型](#%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80%E7%B1%BB%E5%9E%8B)\n    - [编译型语言](#%E7%BC%96%E8%AF%91%E5%9E%8B%E8%AF%AD%E8%A8%80)\n    - [解释型语言](#%E8%A7%A3%E9%87%8A%E5%9E%8B%E8%AF%AD%E8%A8%80)\n  - [V8](#v8)\n- [内存空间](#%E5%86%85%E5%AD%98%E7%A9%BA%E9%97%B4)\n  - [代码空间](#%E4%BB%A3%E7%A0%81%E7%A9%BA%E9%97%B4)\n  - [栈空间](#%E6%A0%88%E7%A9%BA%E9%97%B4)\n  - [堆空间](#%E5%A0%86%E7%A9%BA%E9%97%B4)\n- [执行上下文](#%E6%89%A7%E8%A1%8C%E4%B8%8A%E4%B8%8B%E6%96%87)\n  - [何时开始](#%E4%BD%95%E6%97%B6%E5%BC%80%E5%A7%8B)\n  - [生命周期](#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F)\n- [闭包](#%E9%97%AD%E5%8C%85)\n  - [定义](#%E5%AE%9A%E4%B9%89)\n  - [产生](#%E4%BA%A7%E7%94%9F)\n  - [例子](#%E4%BE%8B%E5%AD%90)\n  - [作用](#%E4%BD%9C%E7%94%A8)\n  - [销毁](#%E9%94%80%E6%AF%81)\n- [this](#this)\n  - [设置优先级](#%E8%AE%BE%E7%BD%AE%E4%BC%98%E5%85%88%E7%BA%A7)\n  - [解决this太活跃的问题](#%E8%A7%A3%E5%86%B3this%E5%A4%AA%E6%B4%BB%E8%B7%83%E7%9A%84%E9%97%AE%E9%A2%98)\n- [Arrow Function](#arrow-function)\n- [注意的点](#%E6%B3%A8%E6%84%8F%E7%9A%84%E7%82%B9)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n### v8引擎基本原理\n- **编译器**: Compiler\n- **解释器**: Interpreter\n- **抽象语法树**: AST\n- **字节码**: Bytecode\n- **即时编译器**: JIT\n\n#### 编程语言类型\n##### 编译型语言\n在执行程序之前，会将代码编译成为**二进制**文件；每次运行时只需要运行二进制文件即可，无需重新编译，C/C++, GO等都是编译型语言。生成过程会占用大量内存，因为有中间代码的产生。\n\u003cdiv style=\"text-align:center; margin:auto\"\u003e\u003cimg src=\"img/2019-12-10-13-39-38.png\"\u003e\u003c/div\u003e\n\n##### 解释型语言\n先将源代码翻译成**字节码**，然后逐行解释执行；每次运行时都需要通过**解释器**对程序动态解释及执行; 生成过程不会占用大量内存，因为字节码比中间代码小很多。\n\u003cdiv style=\"text-align:center; margin:auto\"\u003e\u003cimg src=\"img/2019-12-10-13-39-56.png\"\u003e\u003c/div\u003e\n\n#### V8\n- **生成AST**: `tokenize`, `parse`\n- **生成执行上下文**\n- 解释器`Ignition`将AST生成**字节码**\n- **执行代码**(`JIT`)\n  - 如果是第一次执行该代码，则Ignition逐行解释执行\n  - 如果遇到HotSpot代码，则TurboFan进入编译，保存为高效的二进制文件\n\u003cdiv style=\"text-align:center; margin:auto\"\u003e\u003cimg src=\"img/2019-12-10-13-39-05.png\"\u003e\u003c/div\u003e\n\n### 内存空间\n#### 代码空间\n- 用来存储可执行代码\n\n#### 栈空间\n- `先进后出`以维护`执行上下文`顺序\n- 对上下文切换`效率`有要求，只适合存储**小**型数据: `primitive`, `reference`\n- 垃圾回收由`ESP指针`下移来实现\n\n#### 堆空间\n- 适合存储**大**型数据，内存分配和回收会消耗一定时间\n- 存储**对象**(`闭包`), 内存泄露发生在这里\n- 垃圾回收由`GC`来完成, 会被分割成为`新生代`(`副垃圾`回收器 **Scanvenger算法**)和`老生代`(`主垃圾`回收器，**增量标记算法**)\n\n### 执行上下文\n#### 何时开始\n- `全局`运行\n- **调用**`函数`(编译阶段只会将函数存储到堆中)\n- 运行`eval`()\n\n#### 生命周期\n- **代码编译**: `函数`调用或者`全局`才会进入编译;\n  - 创建**变量环境**: `var`(提升定义和初始化-undefined)\n  - 创建**词法环境**: 块级作用域由词法作用域中的小型栈来维护\n    - `let`(只提升定义,状态为uninitialzied), \n    - `const`(只提升定义,状态为uninitialized)\n    - `func 声明`(提升且直接赋值，本身存储在heap中; 会覆盖掉同名变量, 但是可以重新赋值)\n    - `func 表达式`(提升定义和初始化-undefined)\n    - `func 参数`(初始化-undefined)\n  - 确定**词法作用链**: 看**源代码**就能确定: (具体实现是有`outer`引用实现的)\n    - 全局作用域\n    - 函数作用域\n    - 块级作用域\n    - **对象并不构成作用域**\n  - 确定`this`指向: `new` \u003e `apply/call/bind` \u003e `object context` \u003e `gloabl/undefind`\n- **代码执行**\n  - 函数参数赋值\n  - 标识符赋值(`const`未赋值会报错，`let`未赋值会默认为`undefined`)\n  - 函数调用(会创建新的`执行上下文`)\n- **垃圾回收**\n  - 调用栈中的垃圾回收是靠ESP指针下移来实现的(不是GC)\n\n### 闭包\n#### 定义\n- 在JavaScript 中，根据**词法作用域**的规则，内部函数总是可以访问其`外部作用域`中声明的变量，当通过调用一个`外部函数`返回一个`内部函数`后，即使该外部函数的**执行上下文**已经销毁，但是内部函数引用的**其外部的**变量依然以`对象`的形式保存在**内存堆**中，我们就把这些`变量的集合`称为**闭包**。比如外部函数是`foo`，那么这些变量的集合就称为`foo`函数的**闭包**。\n- **闭包的本质是返回`函数`及其所引用的`外部变量`，外部变量的查询依然遵照`作用域链`的原则**\n\n#### 产生\n- 编译期间: 预先扫描函数、\n- 遇到函数时，要先`预扫描`一遍\n- 如果引用外部变量，则会形成闭包的引用，这是闭包并未在内存中建立\n- 只有\n\n#### 例子\n- 1号栗子\n```javascript\nfunction a() {\n  const x = 123;\n  function b(){\n    console.log(x);\n  }\n  return b;\n}\na()(); // x 是b()的闭包；\n```\n- 2号栗子\n```javascript\nvar bar = {\n    myName:\"time.geekbang.com\",\n    // 不会close over上面的myName,因为上层是对象\n    printName: function () {\n        console.log(myName)\n    }    \n}\nfunction foo() {\n    let myName = \"极客时间\"\n    return bar.printName\n}\nlet myName = \"极客邦\"\nlet _printName = foo()\n_printName()\nbar.printName()\n```\n#### 作用\n- **数据封装**(data as private)\n- **工厂模式**(Factory Pattern)\n- **模块基础**(Module Pattern)\n#### 销毁\n- 伴随着`引用它的函数`的销毁而销毁\n- 如果引用闭包的**函数**是一个`全局变量`，则闭包会一直存在直到`页面关闭`，因此可能会造成内存泄露\n```javascript\nfunction play1() {\n  const x = 1;\n  console.log(x);\n}\nfunction get(){\n  return play1;\n}\nget()();\n```\n- 如果引用闭包的**函数**是个`局部变量`，等函数销毁后，在**下次** JavaScript引擎执行垃圾回收时，判断闭包这块内容如果已经不再被使用了，那么JavaScript引擎的垃圾回收器就会回收这块内存。\n```javascript\nconst x = 1;\n\nfunction play1() {\n  console.log(x);\n}\n\nfunction get(){\n  function play2() {\n    console.log(x);\n  }\n  return play2;\n}\n\nget()();\n```\n- 如果该`闭包`会一直使用，那么它可以作为`全局变量`而存在；\n- 如果使用频率不高，且占用内存较大的话，那就尽量让它成为一个`局部变量`;\n- 可以沟通设置闭包函数为null来释放闭包\n\n### this\n#### 设置优先级\n- `new` \n- `call`/`bind`/`apply` **死绑定**\n- `object context`\n- `global or Window`(non-strict)/`undefined`(strict)\n\n#### 解决this太活跃的问题\n- 保存`this`为`self`变量然后传入(从外层到内层)\n- 使用`Arrow Function`\n\u003e 本质上都是将`this`机制转化为`scope chain`机制\n\n### Arrow Function\n- 会创建新的执行上下文\n- 会创建新的作用域\n- 从外部函数返回后，会产生闭包\n- `this`的查找依赖于Scope Chain\n```javascript\nvar myObj = {\n  name : \"极客时间\", \n  showThis: function(){\n    console.log(this)\n    var bar = () =\u003e {\n      this.name = \"极客邦\"\n      console.log(this)\n    }\n    bar()\n  }\n}\nmyObj.showThis()\nconsole.log(myObj.name)\nconsole.log(window.name)\n```\n\n\n### 注意的点\n- 函数调用时才会对其进行编译\n- 函数编译时，变量和内部函数声明会被赋值，var定义及初始化为被提升，let，const的定义会被提升，不会被初始化。\n- 变量和函数重名时，函数提升优先级更高; 但是可以被重新赋值\n```javascript\nalert(a);//输出：function a(){ alert('我是函数') }\nfunction a(){ alert('我是函数') }//\nvar a = '我是变量';\nalert(a);   //输出：'我是变量'\n```\n- let在未赋值后使用，将自动化初始化为undefined\n```javascript\nlet b;\nconsole.log(b);\n```\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeekeast%2Fdeep-javascript-v3","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeekeast%2Fdeep-javascript-v3","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeekeast%2Fdeep-javascript-v3/lists"}