JS面试基础(一) 垃圾回收,变量与运算符
前提 : js语言特点
垃圾回收机制:
垃圾回收机制也简称做GC ,在js中,内存的分配是自动完成的,当分配的内存不在被使用之后就会自动被垃圾回收器自动回收.
JS的生命周期:(js中内存使用的周期)
- 分配内存: 在声明变量等操作的时候会自动分配内存
- 内存的使用与读写
- 内存回收: 当内存不再被使用的时候会自动进行内存的回收 并销毁声明的变量等
- 注意:
- 全局变量不会在使用完之后被回收,而是等程序结束运行或是页面关闭才会进行回收
- 局部变量在使用之后就会自动被回收
- 内存泄露: 程序分配完内存之后未被释放或无法被释放
js的作用域:
1.js的作用域大致可以分为三种 :
- 局部作用域:
- 函数作用域: 在函数内部声明的变量 只能在函数内部使用 参数也可以看作函数的内部变量 函数执行完毕之后就会被清空
- 块作用域: 只要是被{ }扩起来的就是块作用域 比如循环 对象 等等 块内部声明的变量可能会出现被外部访问的情况 比如使用var声明的变量具有变量提升的特点
- 全局作用域:
- 在js文件或script中直接声明的变量是全局变量 全局都可以访问
- 为window对象动态添加的属性默认为全局
- 函数中使用变量 但没有使用声明字符的变量是全局变量
2.作用域链: 本质就是变量的查找机制 如果当前作用域查找不到会依次逐级查找父级作用域知道全局作用域(类似事件冒泡),子集可以访问父级,但是父作用域不能访问子作用域
一:变量与数据类型,变量提升
(1) 变量声明
在 JavaScript 中,用于声明变量的关键字有:
| 关键字 | 特点 | 作用域 | 是否可重复声明 | 是否有变量提升 |
|---|---|---|---|---|
var | 可重复声明,函数作用域 | 函数级 | ✅ | ✅ |
let | 块级作用域,不可重复声明 | 块级 | ❌ | ❌(存在暂时性死区) |
const | 常量,不可更改 | 块级 | ❌ | ❌ |
var a = 10; // 函数作用域,可重复声明
let b = 20; // 块作用域,不可重复声明
const c = 30; // 常量,声明时必须赋值
(2) 数据类型
JavaScript 是动态类型语言,数据类型分为两大类:
基本类型(值类型)
String、Number、Boolean、Undefined、Null、Symbol、BigInt
let str = 'hello';
let num = 100;
let flag = true;
let und = undefined;
let nul = null;
let sym = Symbol('id');
let big = 123n;
引用类型(复杂类型)
Object、Array、Function、Date、RegExp
let obj = { name: 'Tom', age: 20 };
let arr = [1, 2, 3];
let fn = function () { console.log('hi'); }
typeof 检测类型
typeof 123 // "number"
typeof 'abc' // "string"
typeof null // "object"(历史遗留问题)
typeof undefined // "undefined"
typeof [] // "object"
typeof function(){} // "function"
(3)变量提升
1.变量提升是js设计上的一个缺陷, 代码在执行之前会在当前作用域下检测所有用var声明的变量提升的当前作用域的最前面(var声明变量造成的缺陷,而且只提升声明 不提升赋值)
console.log(num);//undefinevar num=10console.log(num2=10)//10var num2
2.变量提升具体执行过程
定义过程:
console.log(web)
var web='houdunren'
执行过程:
var声明的变量,会提前将声明过程提升到 作用域的最前面,但是他不会提升赋值过程,导致了变量只声明但是没赋值。
var web;
console.log(web)
web="houdunren"
建议: 在开发过程中尽量不去使用var字段去声明变灵 而是改用let和const 是因为let 和 const存在 临时死区(tdz)
(4)let和count的临时死区
临时死区(Temporal Dead Zone):它指的是在代码执行过程中,从作用域开始到 let 或 const 变量声明语句之间的区域,在这个区域内访问这些变量会导致引用错误。在声明变量之前,操作变量会抛出ReferenceError的异常。这就避免了var声明变量提升的问题
(5)变量冻结与全局污染
1.全局污染
在作用域中未声明的变量直接使用会造成全局污染,这里的污染不止陷于本作用域 还会污染其他引入了该js文件的其他js文件
function show() {web='houdunren'
}
show()
console.log(web);
// 运行会发现本来在块作用域下的 未声明变量web 居然在全局中可以使用了 这就是全局污染
// 这里全局污染同样污染括了引入的其他js文件2.变量冻结:
简单来说就是使用Object.freeze()方法,然后被冻结的变量就不能更改了。
const HOST={url:'https://www.houdunren.com/api',port:443
};
// 对象冻结 冻结之后代码不再可以修改
Object.freeze(HOST);
HOST.port=80;
console.log(HOST);二:运算符与表达式
(1) 算术运算符
+、-、*、/、%、++、--
let a = 5, b = 2;
console.log(a + b); // 7
console.log(a % b); // 1
(2) 比较运算符
>、<、>=、<=、==、===、!=、!==
console.log(1 == '1'); // true(类型转换后比较)
console.log(1 === '1'); // false(严格比较,类型不同)
(3) 逻辑运算符
&&(与)、||(或)、!(非)
console.log(true && false); // false
console.log(true || false); // true
console.log(!true); // false
(4) 赋值运算符
=、+=、-=、*=、/=、%=
let x = 10;
x += 5; // 相当于 x = x + 5
console.log(x); // 15
(5) 展开运算符
展开运算符:... 一般用于展开数组 可以用来合并数组等等
// ‘...’展开运算符 const arr=[1,2,3,4,5,6]//1.展开数组 就是将一个数组拆散成分散的变量// ...arr=1,2,3 console.log(...arr)// 一般用于求数组最大值,合并数组(合并列表)console.log(Math.max(...arr));//6// 合并const arr1=[1,2,3]const arr2=[4,5,6]arr1.push(...arr2)//1,2,3,4,5,6console.log(arr1);
使用展开运算符合并对象
不只是可以合并对象 也可以对对象做一次浅拷贝
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };// 合并对象
const merged = { ...obj1, ...obj2 };
console.log(merged); // { a: 1, b: 2, c: 3, d: 4 }