JavaScript学习笔记

文章目录

JS基础

检测当前运行环境

js 复制代码
console.log(typeof window === 'undefined' ? 'Node' : 'Browser');

进阶做法:用 globalThis

js 复制代码
console.log(globalThis.window ? 'Browser' : 'Node');

globalThis 是所有环境都存在的统一顶级对象;在 Node 里 globalThis.windowundefined,在浏览器里指向 window 本身。

浏览器端 JavaScript组成:(3个部分)

组成 作用 核心接口 Demo
ECMAScript 语言本体 (语法 + 内建对象) Array, Promise Math.random()
DOM (Document Object Model) 操作页面元素 document.querySelector, Element.classList js document.body.style.background='lavender';
BOM (Browser Object Model) 操作浏览器窗口/历史/地址 location, history, navigator js alert(location.href);
Node Demo:读文件并返回大小
js 复制代码
//  size.js
//运行命令 :node size.js Test111.txt
import { statSync } from 'fs';
import { resolve } from 'path';

const file = resolve(process.argv[2]);
const { size } = statSync(file);
console.log(`File size: ${size} bytes`);

输出:

复制代码
File size: 57 bytes

文件不存在

复制代码
node size.js nofile.txt

会抛出错误并终止执行:

复制代码
Error: ENOENT: no such file or directory, stat '/F:zyx/nofile.txt'

未提供参数 (process.argv[2]undefined就会有这个问题)

复制代码
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined

JS语法

变量声明 let / const / var

要点:

  • letconst 拥有块级作用域,存在「暂时性死区」(TDZ),禁止在声明前访问。

  • const 声明后不可重新赋值,但若值是对象,其属性仍可变。

  • var 具函数作用域并会变量提升,容易造成混淆,通常仅维护旧代码时使用。

js 复制代码
{
  console.log(typeof value);   // ⚠️ ReferenceError(TDZ),这就是在声明之前访问了,声明在下一句!
  let value = 42;
  const PI = 3.1416;
  // PI = 3;       // ⚠️ TypeError: Assignment to constant variable
}

在进入花括号后,value 处于 TDZ,尝试访问即抛错。

PI 一旦赋值后不可再次赋值。

输出:(TDZ声明前访问)

js 复制代码
ReferenceError: Cannot access 'value' before initialization

数据类型

要点:

  • 基本数据类型:number (含 NaNInfinity)、stringbooleanundefinednullsymbolbigint
  • 引用数据类型:ObjectArrayFunction、自定义对象......)
  • 注意:内置对象 Function、Array、Date、RegExp、Error 等都是属于 Object 类型。也就是说,除了那七种基本数据类型之外,其他的,都称之为 Object 类型。
js 复制代码
console.log(typeof null);       // 为何是 "object"?
console.log(typeof 10n);        // "bigint"
console.log(typeof Symbol());   // "symbol"

早期实现遗留导致 typeof null 返回 "object"

Symbol() 生成独一无二的标识符,用于对象私有键。

基本数据类型举例

js 复制代码
var a = 23;
var b = a;

a++;

console.log(a); // 打印结果:24
console.log(b); // 打印结果:23

a 和 b 都是基本数据类型,让 b 等于 a,然后改变 a 的值之后,发现 b 的值并没有被改变

引用数据类型举例

js 复制代码
var obj1 = new Object();
obj1.name = 'smyh';

// 让 obj2 等于 obj1
var obj2 = obj1;

// 修改 obj1 的 name 属性
obj1.name = 'vae';

console.log(obj1.name); // 打印结果:vae
console.log(obj2.name); // 打印结果:vae

obj1 和 obj2 都是引用数据类型,让 obj2 等于 obj1,然后修改 obj1.name 的值之后,发现 obj2.name 的值也发生了改变

栈内存和堆内存

JS 中,所有的变量 都是保存在栈内存中的。

基本数据类型

基本数据类型的值,**直接保存在栈内存中。**值与值之间是独立存在,修改一个变量不会影响其他的变量。

引用数据类型

对象是保存到堆内存 中的。每创建一个新的对象,就会在堆内存中开辟出一个新的空间;而变量保存了对象的内存地址(对象的引用),保存在栈内存当中。如果两个变量保存了同一个对象的引用,当一个通过一个变量修改属性时,另一个也会受到影响。

这一点和py是很像的。

Undefined:未定义类型

Undefined 类型的值只有一个,就是 undefind。比如 var a = undefined

使用 typeof 检查一个 undefined 值时,会返回 undefined。

undefined 的出现有以下几种情况:

  • 变量已声明,未赋值(未初始化),一个变量如果只声明 了,但没有赋值 ,此时它的值就是 undefined
  • 变量未声明(未定义),如果你从未声明一个变量,就去使用它,则会报错(这个大家都知道);此时,如果用 typeof 检查这个变量时,会返回 undefined
  • 函数无返回值时(在定义一个函数时,如果末尾没有 return 语句,那么,其实就是 return undefined。)
  • 调用函数时,未传参

调用函数时,如果没有传实参,那么,对应形参的值就是 undefined。

js 复制代码
function foo(name) {
    console.log(name);
}

foo(); // 调用函数时,未传参。执行函数后的打印结果:undefined

实际开发中,如果调用函数时没有传参,我们可以根据需要给形参设置一个默认值:

复制代码
function foo(name) {
    name = name || 'qianguyihao';
}

foo();

等学习了 ES6 之后,上方代码也可以这样写:

复制代码
function foo(name = 'qianguyihao') {}

foo();
Null:空对象

如果你想定义一个变量用来保存引用类型(也就是对象),但是还不确定放什么内容,这个时候,可以在初始化时将其赋值为 null。

从语义上讲,null表示一个空对象,所以使用 typeof 检查一个 null 值时,会返回 object。举例:

js 复制代码
var myObj = null;
cosole.log(typeof myObj); // 打印结果:object

undefined 实际上是由 null 衍生出来的,所以null == undefined的结果为 true。null === undefined 的结果是 false。它们虽然相似,但还是有区别的,其中一个区别是,和数字运算时:

  • 10 + null 结果为 10。
  • 10 + undefined 结果为 NaN。

运算符

  • 算数:+ - * / % **
  • 比较:=== !== > < >= <=(务必用全等 ===
  • 逻辑:&& || !,含短路行为
  • 三元:condition ? A : B
  • 模板字符串:用反引号 ```, 可内插 ${...}

Demo

js 复制代码
const score = 75;
const ok = score > 60 ? 'pass' : 'fail';
const msg = `Result: ${ok}, score = ${score}`;
console.log(msg);
  • score > 60 为真,三元返回 'pass'
  • 模板字符串直接插入变量,无需拼接。

输出

复制代码
Result: pass, score = 75

流程控制

条件:if...else, switch

循环:for(索引)、for...in(枚举键)、for...of(遍历可迭代对象)

break / continue 控制跳出或跳过。

Demo

复制代码
const arr = ['a', 'b', 'c'];
for (const val of arr) {
  if (val === 'b') continue;
  console.log(val);          // 打印 'a' 和 'c'
}
  • for...of 直接拿值;当遇到 'b'continue 跳过本轮。

输出

复制代码
a
c

函数

  • 声明式:有函数提升
  • 表达式 / 箭头函数:在赋值后才能调用
  • 默认参数与剩余参数 ...args
  • 箭头函数不绑定自己的 this / arguments

Demo

复制代码
const sum = (...ns) => ns.reduce((a, b) => a + b, 0);
console.log(sum(1, 2, 3, 4));    // 10

解释

  • ...ns 收集任意个参数生成数组。
  • reduce 累加得到总和。

输出

复制代码
10

作用域与闭包

  • JS 使用词法作用域(静态作用域)
  • 闭包 = 函数 + 其引用的外部变量,即便外部函数已返回。

Demo

复制代码
function makeCounter() {
  let count = 0;
  return () => ++count;
}

const inc = makeCounter();
console.log(inc()); // 1
console.log(inc()); // 2
  • inc 始终持有对 count 的引用形成闭包,累加状态得以保留。

输出

复制代码
1
2

对象

  • 字面量简写:{x} 等价于 {x: x}
  • 计算属性:['prop' + i]: value
  • 方法简写:say() {}
  • 可选链:obj?.child?.name 防止空值报错。

Demo

复制代码
const x = 5;
const o = {
  x,                    // 简写
  ['y' + 1]: 6,         // 计算属性名 y1
  say() { return this.x }
};
console.log(o.y1, o.say()); // 6 5

输出

复制代码
6 5

数组

  • 高阶函数:map, filter, reduce
  • 解构、扩展 ...
  • Array.isArray(obj) 判断。

Demo

复制代码
const raw = [1, 2, 3, 4];
const squares = raw.map(n => n ** 2);     // [1,4,9,16]
const evens = raw.filter(n => n % 2 === 0); // [2,4]
const total = raw.reduce((a, b) => a + b, 0); // 10
const [head, ...rest] = raw; // 解构
console.log(squares, evens, total, head, rest);

输出

复制代码
[ 1, 4, 9, 16 ] [ 2, 4 ] 10 1 [ 2, 3, 4 ]

模块化

  • ES Module (浏览器 / Node ≥ v14 原生支持)
    • export const foo = ...; / export default ...;
    • import foo, { bar } from './lib.js';
  • CommonJS (旧版 Node)
    • module.exports = ...; / const foo = require('./lib');

Demo (ESM)

js 复制代码
// math.js
export const add = (a, b) => a + b;

// main.mjs
import { add } from './math.js';
console.log(add(2, 3));   // 5

输出

复制代码
5

异步基础

  • 回调 → Promiseasync/await 是演进路线。
  • 静态方法:Promise.all, Promise.race
  • await 只能在 async 函数或顶级 module 中使用。

Demo

复制代码
function delay(ms) {
  return new Promise(res => setTimeout(res, ms));
}

(async () => {
  console.time('t');
  await delay(500);
  console.timeEnd('t');      // ≈ 500ms
})();
  • delay 返回在指定毫秒后解决的 Promise。
  • await 暂停执行,确保时序易读。

输出

复制代码
t: 500.XXXms

错误处理

  • try / catch / finally 捕获同步 & await 抛出的异常。
  • 自定义错误类继承 Error

Demo

js 复制代码
class BadInputError extends Error {
  constructor(msg) { super(msg); this.name = 'BadInputError'; }
}

function parseJson(str) {
  if (typeof str !== 'string') throw new BadInputError('Need string');
  return JSON.parse(str);
}

try {
  parseJson(42);
} catch (e) {
  console.error(e.name, e.message);   // BadInputError Need string
} finally {
  console.log('done');
}

输出

复制代码
BadInputError Need string
done
相关推荐
冬夜戏雪14 分钟前
【学习日记】【刷题回溯、贪心、动规】
学习
一只爱做笔记的码农17 分钟前
【BootstrapBlazor】移植BootstrapBlazor VS工程到Vscode工程,报error blazor106的问题
笔记·学习·c#
木西20 分钟前
人间观察:关于健康、善良与选择的思考
笔记
星轨初途34 分钟前
数据结构排序算法详解(2)——选择排序(附动图)
c语言·数据结构·经验分享·笔记·b树·算法·排序算法
蚂蚁集团数据体验技术35 分钟前
一个可以补充 Mermaid 的可视化组件库 Infographic
前端·javascript·llm
xixixi777771 小时前
“C2隐藏”——命令与控制服务器的隐藏技术
网络·学习·安全·代理·隐藏·合法服务·c2隐藏
名字不相符1 小时前
攻防世界WEB难度一(个人记录)
学习·php·web·萌新
华仔啊1 小时前
还在用 WebSocket 做实时通信?SSE 可能更简单
前端·javascript
陈天伟教授2 小时前
基于学习的人工智能(4)机器学习基本框架
人工智能·学习·机器学习
7***37452 小时前
DeepSeek在文本分类中的多标签学习
学习·分类·数据挖掘