☰
javascript-in-one-pic:一张脑图掌握 JavaScript 语法全貌
2026/10/15 17:33:21 网站建设 项目流程
  • 教程

【免费下载链接】javascript-in-one-pic

Learn javascript in one picture.

项目地址:https://gitcode.com/gh_mirrors/ja/javascript-in-one-pic
点击查看免费下载

本指南围绕开源仓库 javascript-in-one-pic 的核心产物——一张汇总 JavaScript 语法与核心概念的脑图(Mind map)展开,系统介绍该项目的设计思路、仓库文件资源与完整的知识结构。读完本文,你可以快速建立对 JavaScript 的整体认知、按图定位具体语法细节,并把脑图内容直接用作日常开发时的语法速查手册。

javascript-in-one-pic 项目核心产物:JavaScript 语法知识脑图总览

项目定位:用一张图承载整个 JavaScript 语法体系

从个人笔记到开源语法手册

按项目 README(README.md)与中文版(README-zh.md)的说明,该项目最初是作者为个人使用而记录的 JavaScript 语法与基本概念笔记,同时兼作教学课程大纲。在整理过程中作者发现,用脑图(Mind map)来总结一门编程语言的效果出乎意料地好:这种树状结构看起来就像一本 JavaScript 手册的目录从细节上被逐层扩充,既能从宏观上把握语言全貌,又能非常快速地定位到某个实用的语法细节。

因此,项目的核心交付物只有一张图——js in one pic.png——它把 JavaScript 的标识符规则、数据类型、运算符、作用域、引用类型与流程控制等主干知识组织成一张可读的总览图。

适合谁使用

README-zh 对目标读者给出了清晰的分层建议:

  • 完全没有编程经验的新手:不适合在无人指导的情况下独自学习;
  • 拥有其他编程语言经验的 JavaScript 新手:可以把脑图作为学习提纲使用;
  • 有经验的 JavaScript 开发人员:更适合把它当作语法手册随时查阅。

作者还建议将导出的 PDF 打印出来贴在电脑旁边,作为常驻的参考材料。

工具链与文件格式

从 README 的 "About this project" 一节可以确认项目使用的工具链与交付格式:

  • 脑图使用Mindnode(macOS 思维导图工具)绘制;
  • 同时导出PDF、PNG、OPML三种格式;
  • 提供*.mm文件,可用开源脑图软件FreeMind继续编辑;
  • 项目整体完成后计划再发布 SVG 格式(README 以 issues #9 跟踪该事项);
  • README 的 "Online version" 一节还提供了在线脑图入口(Online Mindmap),并列出待办项 "Syntax highlight"。

仓库资源一览:五种格式各取所需

仓库根目录下与知识内容直接相关的文件如下,均可按需选用:

文件格式用途
js in one pic.pngPNG 位图一张总览图,直接查看、分享
js in one pic.pdfPDF打印输出,贴在电脑旁当手册
js in one pic.mmFreeMind 工程用 FreeMind 打开即可继续编辑
js in one pic.opmlOPML(大纲标准格式)可导入大多数主流脑图/大纲工具
js in one pic.mindnodeMindnode 源工程保留原始的绘制工程(含 contents.xml、viewState.plist 等)

其中 js in one pic.mm 与 js in one pic.opml 是纯文本的结构化源文件,内容与 PNG 中的脑图一一对应,本文后续的"脑图内容详解"即以其为准逐条展开。此外仓库还提供 5 种语言的 README:README.md、README-zh.md、README-zh_TW.md、README-pt_BR.md、README-es_MX.md。

颜色标记:脑图里的"三色信号灯"

README 用三个徽章规定了脑图配色的语义,这在阅读和继续编辑脑图时非常关键:

  • 不推荐使用(not recommended):#7E1600 深红
  • 重要(important):#4E8D20 绿
  • 注意(warning):#DE2B00 橙红

从 js in one pic.mm 的源码(FreeMind XML 的COLOR属性)可以印证这些颜色确实被落实到具体知识点上,例如:

  • a = 123; // global(未用var声明、直接赋值的全局变量)以#800000深红色标注,属于"不推荐"类写法(js in one pic.mm);
  • "Object (basic)" 与 "Object (OOP)" 两个主干节点以及 "root of everything" 以#008000/#057F00绿色标注为重要内容(js in one pic.mm、js in one pic.mm);
  • 数组的shift/unshift/sort/reverse/splice下方注释 "// will change the array" 以#FF0000红色标注为警告,提示这些方法会原地修改原数组(js in one pic.mm)。

另外脑图中还预留了一个空的 "Tips" 分支(js in one pic.mm),从结构看是用于日后补充易错提示的预留位置。

脑图内容详解(按主干逐层展开)

脑图共分六大主干:Identifier(标识符)、Comments(注释)、Data type(数据类型)、Operators(运算符)、Scope(作用域)、Reference type(引用类型),以及一个相对独立的 Flow control(流程控制)分支。以下按 js in one pic.mm 的实际内容逐一展开,并补充必要的原理说明。

Identifier 标识符

标识符分支(js in one pic.mm)覆盖以下规则:

  • 大小写敏感:a != A;
  • 开头字符:必须以字母、下划线_或美元符号$开头,其中字母既包括 ASCII 字母也包括 Unicode 字母;
  • 关键字(key words):break; case; catch; continue; default; delete; do; else; finally; for; function; if; in; instanceof; new; return; switch; this; throw; try; typeof; var; void; while; with;
  • 保留字(Reserved words),分两种场景:
    • 非严格模式下:class; const; enum; export; extends; import; super;
    • 'use strict'严格模式下额外保留:implements; interface; let; package; private; protected; public; static; yield;
  • 变量声明:
    var a; // local(局部变量) a = 123; // global(未声明即赋值,成为全局变量)

    其中直接赋值而不加var的写法在脑图中被标记为"不推荐"(深红色),因为它会在全局作用域上隐式创建变量,容易造成命名冲突与难以追踪的 bug。

Comments 注释

注释分支(js in one pic.mm)只列出两种基础写法:

// single line 单行注释 /* multi-line comments */ 多行注释

Data type 数据类型

数据类型是脑图中最庞大的分支之一(js in one pic.mm),包含六类基础类型与函数类型。

Number(数字)
  • typeof返回'number';

  • 常见取值:0、1.2、045(八进制)、0x56(十六进制)、0.314e2(科学计数法)、NaN;

  • 类型转换Number()系列:

    parseInt("2.7", 10); // 2 parseInt('10', 2); // 2(按二进制解析) parseFloat('2.5'); // 2.5 isNaN(parseFloat('a')); // true
  • 支持运算符+ - * / %以及比较运算符<, <=, >, >=, !=, ==。

String(字符串)
  • typeof返回'string';

  • 取值可用双引号"Hello"或单引号'World';

  • 转换:String()/toString():

    var a = 8; a.toString(2); // '1000'(转为二进制字符串)
  • **不可变(immutable)**特性:

    var a = 'ABC'; a[0]; // 'A' a[0] = 'D'; a; // 'ABC'(赋值不生效,字符串不可变) var a = 'abc'; a = a + 'd'; a; // 'abcd'(重新赋值得到新字符串)
  • 运算符:+用于拼接,以及比较运算符<, <=, >, >=, !=, ==。

Boolean(布尔值)
  • typeof返回'boolean';

  • 取值只有true/false;

  • Boolean()转换规则(脑图按输入类型分组给出):

    • number:Boolean(0); // false、Boolean(NaN); // false、Boolean(!0); // true
    • string:Boolean(''); // false、Boolean('*'); // true
    • object:Boolean(null); // false、Boolean({}); // true
    • undefined:Boolean(undefined); // false

    归纳起来即:0、NaN、空字符串、null、undefined 在布尔上下文中均为 falsy,其余值(包括空对象{})为 truthy。

Undefined(未定义)
  • typeof返回'undefined';

  • 唯一取值就是undefined;

  • undefined≠ "未声明"(Not defined),这是脑图特意强调的易错点:

    undefined == undefined; // true var a; a == undefined; // true(已声明但未赋值) console.log(d); // Error(d 从未声明,直接报 ReferenceError)
Object(基础)与 Null
  • typeof返回'object';

  • 字面量创建:

    var p = { name: 'Ad', 'age': 24 }; var q = {}; q.name = 'Bob'; q.age = 24; console.log(q.name); // 'Bob' console.log(q['age']); // 24(既支持点号也支持方括号访问)
  • 构造函数创建:

    var p = new Object(); p.sayHi = function(){ console.log('Hi!'); } p.sayHi(); // 'Hi!'
  • Null(属于"类基本类型"):typeof null同样返回'object'(历史遗留行为);null == undefined; // true(宽松相等成立,因为null被视为"未定义对象")。

Function(基础)
  • typeof返回'function';

  • 三种创建方式:

    var a = function(arg1, arg2){ // 函数表达式 //func body; } function a(arg1, arg2){ // 函数声明 //func body; } (function(arg1, arg2){ // 立即执行函数表达式(IIFE) //func body; })
  • 函数内部(inside function):

    • 参数按顺序传入:
      var f = function(x, y){ console.log('x: ' + x + ', y: ' + y); }; var x = 'x', y = 'y'; f(x, y); // x: x, y: y f(y, x); // x: y, y: x
    • 缺省参数为undefined:
      var f = function(x){ console.log(x); }; f(); // undefined
    • 内置arguments对象按索引保存所有实参:
      var f = function(){ console.log(arguments); }; f(3, 2, 1); // { '0': 3, '1': 2, '2': 1 }
    • return用于返回结果(脑图单列 "return" 节点提示其作用)。

Operators 运算符

运算符分支(js in one pic.mm)重点讲解类型转换与比较语义。

算术与强制类型转换(casting)

+ - * / %四个基础运算符中,脑图重点演示了+与-在混合类型下的转换优先级:

  • +的转换优先级:string > number > boolean(只要有一端是字符串,+就偏向拼接):

    '1' + 2; // '12' 3 + '4'; // '34' '5' + false;// '5false' 6 + true; // 7
  • -的转换优先级:number > string > boolean(-没有拼接语义,两端都向数字转换):

    '1' - 2; // -1 3 - '4'; // -1 '5' - false;// 5 6 - true; // 5
自增自减与赋值

++a、a--、a+=1、a-=1被归为一组,提醒这些运算符既有返回值又会改变变量本身。

比较运算
  • 关系比较:>, >=, <, <=;
  • 宽松相等:==, !=——只比较值(only value),比较前会做类型转换;
  • 严格相等:===, !==——同时比较值与类型(both value & type);
  • 类型转换视角:a > b本质上等价于a - b > 0,即先按数字规则转换再比较。
逻辑运算
!true; // false true && false; // false false || true; // true

Scope 作用域

作用域分支(js in one pic.mm)是脑图中理论密度最高的一块,包含执行上下文、作用域链与闭包三个子主题,脑图以 ASCII 示意图辅助说明。

Execution context 执行上下文

脑图用下面的示意图说明"全局对象 + 执行上下文"的关系:在 Node.js 中全局对象是global,在浏览器中则是window;每个执行上下文内部都有一个 Variable Object(变量对象),存放该上下文中的变量、数据、函数与对象。

+-------------+ +-----------------------+ |Node +------+ |Execution Context | +-------------+ | +-----------------------+ |global = { | +--> |[Variable Object] = { | | | | | | |}; | | | variables | +-------------+ | | | | | data | | | | | | functions | +-------------+ | | | |Browser +-----+ | objects | +-------------+ | | |window = { | | ... | | | | | |}; | |}; | +-------------+ +-----------------------+

每次调用函数都会创建新的执行上下文,并压入 Context Stack(上下文栈);当前执行上下文中的this指向"拥有该函数的对象"。示意图如下:

+-----------------------------------+ |function b() // create new context +-----+ +-----------------------------------+ | |Variable Object = { | | +---------------+ | arguments = ...; | | | | | | | | | | | | | | |}; | | | | |Scope chain = | | | . | | +-------------------------------+ | | | . | | |global | | | | . | | | +---> f = 'no'; | | | | | | | | | | | | | | | +---> function a() | | | | | | | +---> f = 'ye' | | | +---------------+ | | | | | +-> |function b | | | +---> function b() | | +---------------+ | | +---> | | |function a | | | | | | +---------------+ | | +---> | | |global context | | | | | +---------------+ | +-------------------------------+ | Context Stack |this = {Object owns b}; | +-----------------------------------+
Scope chain 作用域链

脑图用如下结构说明作用域链的形态:全局作用域在最外层,函数作用域逐层嵌套,每个函数都有一个指向其外层 Variable Object 的引用,从而形成一条链。变量查找时沿这条链由内向外进行。

+--------------------------------------------+ |Scope Chain | +--------------------------------------------+ +-+global [Variable Object] | | | | | +-> var x; | | | | | | <---------------+ | | | + | | +-> function a() [Variable Object]<+ | | | + | | | | | | | | | +--> var x; | | | | | | | | | | + | | | +--> function b() [Variable Object] | | | | | | <---------------+ | | | + | | +-> function c() [Variable Object]<+ | | | + | | | | | | | | | +--> var x; | | | | | | | | | | + | | | +--> function d() [Variable Object] | | | | | v | +--------------------------------------------+
Closure 闭包

闭包子主题给出的是"闭包 = 函数 + 其作用域链"的示意:内部函数inc引用了外层执行上下文中的变量x,即使外层函数执行完毕,inc通过作用域链依然能访问并修改x。脑图同时给出inc1、inc2两次调用inc()的示例,暗示每次调用都会各自捕获独立的x(从结构可以推断,这正是闭包实现"私有状态"的机制)。

+-------------------+ +-----------------+ |Execution context | +---+[Scope chain] | +-------------------+ | +-----------------+ +> | var x = 100; | | |[Function inc] | | | var inc1 = inc(); +--+ | + | | | var inc2 = inc(); +--+ | +-> x; | | | | | | | | | inc1(); | | +-> [Function] | | | inc1(); | | + | | | inc2(); | | +-> x++; | | | inc1(); | | | | | inc2(); | +-----------------+ +--+ x; | | | +-------------------+

Reference type 引用类型

引用类型分支(js in one pic.mm)涵盖 Function、Array 与面向对象(OOP)的 Object。

Function:一等公民
  • typeof返回'function';

  • 属性:f.length;(形参个数);

  • 函数作为值传递(callback 回调):

    var api = function(){ return { name: 'rainy', age: 24 }; }; var handler = function(d){ console.log('Name: '+d.name+', Age: '+d.age); }; var request = function(api, callback){ callback(api()); }; request(api, handler); // Name: rainy, Age: 24
  • 方法 apply / call / bind:

    // func.apply(thisObj, [arg1, arg2, ...]); // func.call(thisObj, arg1, arg2, ...); // func.bind(thisObj, arg1, arg2, ...); // 关于 thisObj,参见 Scope 分支 var sayHi = function(name){ console.log('Hello, ' + name + '!'); }; sayHi.call(this, 'rainy'); // Hello, rainy! sayHi.apply(this, ['rainy']); // Hello, rainy! sayHi.bind(this, 'rainy')(); // Hello, rainy!

    三者的共同点是指定函数体内的this;区别在于call逐个传参、apply以数组传参、bind返回一个已绑定this(与参数)的新函数而不会立即执行。

Array:数组
  • typeof返回'object'(数组本质是对象);

  • 两种创建方式等价:

    var a = [1, 2, '3', [4, true]]; var a = new Array(1, 2, '3', [4, true]);
  • 属性:a.length; // 4;

  • 常用方法(脑图逐一给出):

    a[0] == 1; // true(下标访问) a[3][1] == true; // true(二维数组访问) a.slice(0, 2); // [1, 2](切片,不修改原数组) a.indexOf(1); // 0(查找元素下标) a.push({}); // 返回新的 a.length(入栈,Mod 修改原数组) a.pop(); // 返回被弹出的元素(Mod 修改原数组) a.join('-'); // ?(自测题:拼接所有元素为字符串) a.toString() == a.join(','); // true var s = 'a,b,c,d'; s.split(','); // ['a', 'b', 'c', 'd'](字符串分割成数组) a.concat(['a', 'b']); // 返回新数组,原数组不变 —— 与 push()(原地修改)对比
  • map / reduce(脑图标注了回调函数签名):

    // arr.map(callback, thisObj) /* callback = function(element, index, arr){ * return element to the same pos of (returned)arr; * }; */ [55, 44, 33, 22, 11].map(function(e, i, arr){ return e/(arr.length-i); }); // [ 11, 11, 11, 11, 11 ] // arr.reduce(callback, init) /* callback = function(prev, curr, index, arr){ * curr 依次遍历 arr 的后续元素; * prev 缓存上一次的返回值,初始值为 init(未传 init 时取 arr[0])。 * }; */ [55, 44, 33, 22, 11].reduce(function(p, c, i, arr){ return p + c/(arr.length-i); }, 55); // 约 84.88(注:原图注释写作 0,实际累加结果约为 84.88)

    上述map示例中每个元素被除以"该元素距离末尾的元素个数 + 1",恰好得到五个 11;reduce示例则演示了带初始值55的累加过程。

  • filter / some / every:脑图列出但未展开代码,属于同类高阶迭代方法;

  • shift / unshift / sort / reverse / splice:以红色警告标注"// will change the array",提示这五个方法都会原地修改原数组;

  • 遍历(iteration)的两种写法:

    for(var i = 0; i < a.length; i++){ console.log(a[i]); } a.forEach(function(ele){ console.log(ele); });
Object(OOP):构造函数、原型链与继承

脑图以 "root of everything"(绿色重要标记)定位 Object,随后展开三个子主题:

构造函数(Constructor)

function Person(name){ this.name = name; this.sayHi = function(){ console.log('Hi ' + this.name + '!'); }; }; var p1 = new Person('Ad'); var p2 = new Person('Bob'); p1.name // 'Ad' p2.sayHi(); // 'Hi Bob!' p1.constructor === Person // true p1 instanceof Person // true p1.sayHi == p2.sayHi // false(每个实例各自拥有独立的 sayHi 函数)

原型链(prototype chain)

function Person(){}; Person.prototype.name = 'Person'; var p1 = new Person(); var p2 = new Person(); p2.name = 'rainy'; console.log(p1.name); // 'Person'(来自原型) console.log(p2.name); // 'rainy'(实例自有属性覆盖原型)

属性归属判断与遍历保护:

p1 instanceof Person // true p1.age = 24; p1.hasOwnProperty('name'); // false(name 来自原型,不是实例自有属性) Person.hasOwnProperty('name'); // true p1.hasOwnProperty('age'); // true(实例自有属性) 'name' in p1 // true(in 会沿原型链查找) 'age' in Person // false(Person 函数本身没有 age)

原型属性共享的经典陷阱(红色警告部分):

// All properties on the prototype are shared among instances Person.prototype.friends = ['Ad', 'Bob']; p1.friends.pop(); // 'Bob'(p1 修改了共享数组) console.log(p2.friends); // ['Ad'](p2 看到的数组也被改掉了) // 推荐做法:结合构造函数与原型 function Person(){ this.friends = ['Ad', 'Bob']; // 引用类型属性放构造函数,每个实例独立一份 }; Person.prototype.name = 'Person'; // 方法/值类型属性放原型,共享

**继承(Inheritance)**的两种方式:

  • 原型链继承:

    function Father(){}; Father.prototype.familyName = 'Good'; function Child(){}; Child.prototype = new Father(); // 让子类原型指向父类实例 var c = new Child(); console.log(c.familyName); // 'Good'
  • 借用构造函数(constructor stealing):

    function Father(){ this.familyName = 'Good'; }; function Child(){ Father.call(this); // 在子类实例上调用父类构造函数 }; var c = new Child(); console.log(c.familyName); // 'Good'

两种方式的差异在于:原型链继承共享父类原型上的方法,而借用构造函数继承能让每个子类实例获得独立的父类实例属性(配合apply/call使用,参见 Reference type - Function 分支)。

Flow control 流程控制

流程控制分支(js in one pic.mm)覆盖五类语句:

if / 三元

if(cond){ state1; }else if(cond2){ state2; }else{ state3; } false ? a : b // 条件为 false 时取 b

switch

switch (day) { case MON: break; case TUE: break; case WEN: break; default: }

while

do { state1; } while(cond) // 先执行一次再判断 while(cond){ state1; } break; continue; // 跳出循环 / 跳过本次迭代

for

for(var i = 0; i < len; i++){ state1; } for(var k in Obj){ // if Obj.hasOwnProperty(k){ console.log('Obj[' + k + '] = ' + Obj[k]); // } }

其中for...in的示例特意注释了hasOwnProperty过滤,这正是为了避开原型链上可枚举属性(与上一节原型链警告相呼应)。

try / catch / finally

var a = {}; try{ a.f(); // 调用不存在的方法 }catch(e){ console.log(e instanceof TypeError); // true (function(){ console.log('a.f()'); // 'a.f()' })(); }finally{ console.log('always'); // 'always'(无论是否抛错都会执行) }

项目进度与 TODO

README 的 TODO 清单用复选框明确标注了脑图的内容覆盖情况,可归纳如下:

主题状态
Function(基础):函数内部 arguments、return已完成
Function:作为值传递(callback 回调)已完成
Function:方法 apply / call / bind已完成
Array:方法 map / reduce已完成
Object(OOP):构造函数、属性已完成
Object(OOP):继承已完成
Scope 作用域已完成
Function:闭包已完成
Flow control:try / catch已完成
Operators:位运算(bitwise)待完成
ES6待完成

此外在线版本的 "Syntax highlight"(语法高亮)也处于待办状态。也就是说,当前脑图覆盖的是 ES5 时代 JavaScript 的核心语法骨架,位运算与 ES6 特性尚未纳入。

相关项目与参考资料

  • 相关项目:仓库维护者以同样的"一张图"形式准备了 Python3 in one pic,Go 语言版本(Go in one pic)在 README 中标明"准备中"。
  • 参考资料(详见 README.md 的 References 小节):《Professional JavaScript for Web Developers》(JavaScript 高级程序设计)、JavaScript Garden、MDN JavaScript 文档,以及作者撰写的"图解 Javascript 上下文与作用域"博文。脑图中 Scope 分支的 ASCII 示意图即源自后者,这一点从脑图文件中的署名与链接可以印证。

开源协议

项目基于 MIT 协议开源,许可与免责条款见 LICENSE。这意味着你可以自由地查看、打印、分发这张脑图,也可以基于*.mm/.opml源文件继续扩展内容(如完成位运算与 ES6 分支),只需保留相应的版权声明。

  • 教程

【免费下载链接】javascript-in-one-pic

Learn javascript in one picture.

项目地址:https://gitcode.com/gh_mirrors/ja/javascript-in-one-pic
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询