隐式转换
在某些操作中,JavaScript 自动将一种数据类型转换为另一种数据类型
以下是常见场景
字符串拼接
用 + 时,如果其中一个操作数是字符串,另一个操作数会被自动转换为字符串
123console.log(1 + "2"); // 输出: "12"console.log("Hello" + 3); // 输出: "Hello3"console.log(true + " world"); // 输出: "true world"
数字运算
数学运算时,非数字类型的值会被隐式转换为数字
1234console.log(10 - "5"); // 输出: 5console.log("10" * 3); // 输出: 30console.log("10" / 2); // 输出: 5console.log("abc" - 1); // 输出: NaN (无法转换为数字)
布尔值 ...
数据类型+类型判断JavaScript数据类型分为基本类型与引用类型。
基本类型包括undefined、null、boolean、number、string、symbol(ES6)、bigint(ES11);
引用类型为object(如数组、函数等)。
类型判断方法如下:
typeof:返回类型字符串,但typeof null返回"object"(历史遗留问题),且无法区分数组与对象(均返回"object")。
instanceof:检测对象原型链是否包含构造函数(如[] instanceof Array为true),但跨全局环境(如iframe)时失效。
Object.prototype.toString.call():精确返回[object Type]格式(如数组返回"[object Array]"),可识别所有内置类型(包括null返回"[object Null]")。
Array.isArray():专用于判断数组,避免instanceof的跨环境问题。
示例对比:
typeof 42 → & ...
单点登录概念
SSO,是一种身份验证机制,运行用户通过一次登录可以访问多个相关但独立的软件系统
一旦用户登录一个系统,所有相关系统都将识别该用户为已认证状态
实现背景
认证中心:颁发令牌
应用A - 应用B:两个独立应用,共享同一个认证中心
技术栈
JS、Nodejs、OAuth 2.0协议
流程
前端部分
用户访问A
A检测登录状态 -> (未登录重定向认证中心)
1234567891011121314151617// 检查本地是否有有效的访问令牌function checkLoginStatus() { const token = localStorage.getItem('accessToken'); if (!token) { // 如果没有令牌,重定向到认证中心 redirectToAuthServer(); } else { console.log('用户已登录'); }}function redirectToAuthServer() ...
原型原型链原型
每个 JS 对象(除 null)都有一个隐藏的 [[Prototype]] 属性,指向它的“原型对象”(简称原型)
原型对象也是一个普通对象,它包含可以被其他对象共享的属性和方法
作用:存放一些属性和方法 + 在JS中实现继承
原型链可以通过实例对象的 __proto__ 属性访问原型
1234const arr = new Array(1, 2, 3)arr.reverse() // 翻转arr.sort() // 排序 // 这些方法都是挂载到Array.prototype上的,可以共享给所有的数组实例使用console.log(Array.prototype === arr.__proto__); // true
所有原型对象的终点是null
原型链的顶端通常是 Object.prototype
当访问一个对象的属性或方法时,JS 会沿着对象的原型链逐级向上查找,直到找到该属性或到达原型链的终点(null)。
12const obj = {};console.log(Object.prototype.__proto__) ...
new基础
new会创建空的新对象{},这个对象会被作为构造函数的上下文(就是this)
新对象会链接到原型,内部属性 [[Prototype]] (__proto__ 指向构造函数的 prototype 属性)
1234567891011121314function Person(name, age) { // 构造函数首字母通常大写,以区分普通函数 this.name = name; this.age = age;}Person.prototype.greet = function () { // 设置原型上的方法 console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);};// 使用 new 创建实例const alice = new Person('Alice', 25); // 创建了一个新的对象 {...} // alice.__pr ...
防抖和节流防抖
重新开始,只执行最后一次
搜索框输入、文本编辑器实时保存
1<input type="text" class="ipt" @keyup="handleKeyUp($event)" />
123456789const timerId = ref(null); // 使用 ref 来存储定时器 IDconst handleKeyUp = function (event) { if (timerId.value !== null) { clearTimeout(timerId.value); // 清除之前的定时器 } timerId.value = setTimeout(() => { console.log(event.target.value); // 打印输入框的值 }, 1000);};
节流
中间禁用,只执行最先一次
快速点击、鼠标滑动、scroll事件、下拉加载、视频 ...
WeakMap & Map核心区别在于键类型、内存管理及可遍历性:
键类型限制:WeakMap 仅接受对象作为键(非对象如字符串、Symbol会报错),而Map支持任意类型键值。
弱引用机制:WeakMap的键是弱引用,若键对象无其他强引用,垃圾回收时自动清除对应条目,避免内存泄漏;Map强引用键,即使对象不再使用,仍保留条目导致内存无法释放。
可遍历性:WeakMap不可遍历(无size、keys()等方法),Map支持迭代器访问所有条目。
API差异:WeakMap仅有get、set、has、delete方法,Map额外提供clear、forEach及迭代接口。
应用场景对比:
WeakMap:适合关联对象与元数据且无需手动清理(如DOM元素绑定事件处理器,元素移除后自动释放)。
Map:需长期维护键值对或遍历操作的场景(如缓存数据、频率统计)。
示例:
12345678910// WeakMap:键为对象,自动清理 const wm = new WeakMap(); let obj = {}; wm.set(obj, 'data ...
SymbolSymbol 是 JavaScript 中一种唯一且不可变的原始数据类型,其核心应用场景和内存管理特性如下:
使用场景
唯一属性键解决对象属性名冲突问题,确保第三方库扩展对象属性时互不影响:
12const LOG_LEVEL = Symbol('log');const config = { [LOG_LEVEL]: 'debug' }; // 避免与可能的现有属性冲突
模拟私有成员通过非枚举特性隐藏内部实现(需配合闭包):
12345678const _counter = Symbol('counter');class MyClass { constructor() { this[_counter] = 0; // 外部无法直接访问 } increment() { this[_counter]++; }}// 注:通过Object.getOwnPropertySymbols仍可访问,非绝对私有
内 ...
深/浅拷贝深浅拷贝的核心区别在于是否递归复制对象的所有层级引用类型属性,常见实现方案如下:
浅拷贝实现
将原始对象或数组中的元素逐个复制到新对象或数组中
只会复制它们的引用,而不会创建这些嵌套对象或数组的新副本(改变原始对象会同时影响拷贝对象)
Object.assign()
12345const obj = { a: 1, b: { c: 2 } };const copy = Object.assign({}, obj);console.log(copy); // { a: 1, b: { c: 2 } }obj.b.c = 3;console.log(copy.b.c); // 输出: 3 (修改了原始对象的嵌套对象,影响到了浅拷贝)
扩展运算符(...)
12345const obj = { a: 1, b: { c: 2 } };const copy = { ...obj };console.log(c ...
内存泄漏
不再使用的内存未被 GC 机制释放,导致 内存占用持续增长,最终可能引发性能问题或程序崩溃。
该问题只存在于启动的相关页面进程中,并不会永久性地占据电脑内存
一旦相关进程结束(关闭浏览器标签、重启浏览器或应用)操作系统会回收该进程占用的所有内存。
导致成因全局变量
意外出现的全局变量
全局变量不会被 GC 回收,直到页面关闭
123function leak() { leakedData = new Array(1000000); // 未使用 var/let/const,变量变为全局变量}
使用严格模式('use strict')避免隐式全局变量
闭包
闭包引用的外部变量会长期驻留内存
12345function createClosure() { const largeData = new Array(1000000); return () => console.log(largeData); // largeData 被闭包引用,会长期驻留内存}const closure = c ...