变量声明
var
存在变量提升特性。使用var
声明的变量,无论是在代码的什么地方声明,都会被提升到当前作用域的最顶部
在函数内部声明的变量,会被提升到函数顶部;全局声明的变量,会被提升到全局作用域顶部let
关键字在ES6引入,块级作用域,仅在声明的块内(if、for等)有效,避免了变量提升和全局变量问题const
关键字在ES6引入,块级作用域,声明常量,声明时必须初始化
闭包
闭包是指在一个函数内部创建另一个函数,并且内部函数可以访问外部函数的变量、参数以及其他内部函数,即使外部函数已经执行完毕
这种机制使得内部函数保留了对外部作用域的引用,即使外部作用域已经不再活跃
闭包用途:
- 封装,内部函数可以访问外部变量,外部函数不能访问内部变量
- 状态持续,闭包可以在函数调用之间保持状态(如计数器)
function counter() { var count = 1; return function() { return count++; } } var testCounter = counter(); console.log(testCounter ()); // 1 console.log(testCounter ()); // 2 console.log(testCounter ()); // 3
- 偏函数应用
注意:
- 被闭包函数访问父级及以上的局部变量,会一直存在与内存中,不会被JavaScript垃圾回收机制回收。因此可能造成**内存泄漏**,导致网页性能问题
- 解决方法:使用完变量后,手动对变量赋值
null
- 解决方法:使用完变量后,手动对变量赋值
- 可能造成内存泄漏:意外的全局变量、闭包、循环引用
参考:https://zhuanlan.zhihu.com/p/651784228
原型链
每个对象都隐含属性 __proto__
,每个函数都包含属性 prototype
所有构造函数的原型链上层都是 Function
的原型
属性有如下关系
function a() {};
var c = new a();
c.__proto__ === a.prototype // true
a.prototype.__proto__ === Object.prototype // true
Function.prototype.__proto__ === a.prototype.__proto__ // true
手写Promise
class MyPromise {
static PENDING = 'pending';
static REJECTED = 'rejected';
static FULFILLED = 'fulfilled';
status;
value;
reason;
constructor(executor) {
this.status = MyPromise.PENDING;
this.value = undefined;
this.reason = undefined;
const resolve = (value) => {
if (this.status === MyPromise.PENDING) {
this.status = MyPromise.FULFILLED;
this.value = value;
}
};
const reject = (reason) => {
if (this.status === MyPromise.PENDING) {
this.status = MyPromise.REJECTED;
this.reason = reason;
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
if (this.status === MyPromise.FULFILLED) {
onFulfilled(this.value);
}
if (this.status === MyPromise.REJECTED) {
onRejected(this.reason);
}
}
}
module.exports = MyPromise;
什么是原型、原型链?
原型:每个函数都有 prototype
,称为原型/原型对象,原型上可以挂在一些属性/方法,每个实例都可以使用。原型可以用作继承
原型链:每个对象都有 __proto__
,这个属性指向它的原型对象,原型对象同时也是一个对象,拥有 __proto__
属性,指向其原型对象,直到指向最顶层的 null
,这种链式结构即为原型链
const a = new String('lan')
a.__proto__ === String.prototype
// true
a.__proto__.__proto__ === Object.prototype
// true
a.__proto__.__proto__.__proto__ === null
// true
事件循环
事件循环是指Nodejs执行非阻塞I/O操作,尽管JavaScript是单线程的,由于大多数内核都是多线程,Nodejs会尽可能将操作装载到系统内核,因此它可以在后台执行多个操作。当某一操作完成时,内核会告诉Nodejs,以便Nodejs可以将相应的回调添加到轮询队列中,最终执行
Nodejs中异步API分类:
- 定时器(
setTimeout
、setInterval
) - I/O操作(文件读写、数据库操作、网络请求)
- node独有(
process.nextTick
、setImmediate
)
同步方法执行完毕后,开始事件循环,事件循环自上而下循环执行,三个队列均为空时,事件循环会在Poll队列等待,等待新的事件出现后(异步执行完毕),恢复事件循环
其中:
setImmediate
比较特殊,它会直接进入Check队列setTimeout
方法在浏览器环境的最小时间取值为4ms,Nodejs中为1ms
process.nextTick
process.nextTick具有异步特性,但不属于事件循环
在Nodejs的异步模块中,有一个特殊的nextTick
队列,这个队列的优先级比事件循环要高
从Timer -> Poll -> Check
的一个循环成为一个Tick
,process.nextTick
的作用就是将函数插入到每个Tick的头部
微任务队列
微任务队列主要用于处理Promise
的回调函数,微任务队列在nextTick
队列后,在事件循环之前
参考:https://www.bilibili.com/video/BV13A4y1Q7N5/?spm_id_from=333.788&vd_source=51b68c717347dd87b9675be5a4dfdf53
模块化
模块化优势:
- 避免污染命名空间污染
- 更好的分离, 按需加载
- 高复用性、高可维护性
引入过多<script>
导致的问题
- 请求过多
- 过多依赖会导致我们不清楚模块之间的依赖关系,导致先后加载顺序出错
- 难以维护
存在以上原因,出现不同的模块化规范来约束(CommonJS、ES6、AMD、CMD)
参考:https://www.imooc.com/article/details/id/267469
CommonJS 规范
每个模块都有自己的作用域,每个模块的内部数据是私有的,通过暴露一些方法与其他模块进行通信
- 每个文件都是一个独立的模块,每个模块都有一个module对象用来做记录模块的信息
- 通过
module.exports
或exports
可以到处模块
module.exports
和exports
不能混用,否则module.exports
会覆盖exports
- 通过
require()
函数可以导入模块【如果有多个模块同时require
同一个模块,获取到的对象是同一个,Node的缓存机制】
ES Module 规范
- 使用
export
导出模块 - 使用
import
导入模块 - 配置
package.json
的type
字段,启用ES Module
CommonJS 与 ES Module
- CommonJS运行时加载,ES Module编译时加载,后者加载的时机更早
- 在 ES Module 中,没有
__filename
和__dirname
- 在 CommonJS中,this指向当前模块,在ES Module中,this指向
undefined
- 在 ES Module中,
import
引入模块需要传递完整的扩展名,在 CommonJS中,require
可以省略 - ES Module默认运行在严格模式下
Cookies防范XSS攻击
XSS:跨站脚本攻击,攻击者在HTML页面中加入恶意JavaScript脚本,用户浏览页面时,嵌入的脚本代码便会执行
- 反射型XSS攻击
攻击者针对站点定制攻击链接,发送给被攻击者点击
http://www.xxx.com/search?query=<script>alert('XSS')</script>
- 防范:
a. 入参强校验、过滤
b. 输出内容转义,避免特殊字符被浏览器解释为HTML标签
c. 使用HTTP Only cookie
d. 使用安全控件,验证码等
- 防范:
- 存储型XSS攻击
攻击者将恶意脚本插入到输入表单中,在用户提交表单时存储到数据库中- 防范:
a. 入参强校验、过滤
b. 输出内容转移,避免恶意脚本被执行
c. 白名单限制
d. 使用HTTPS
- 防范:
- DOM型XSS攻击
参考:https://zhuanlan.zhihu.com/p/661920779