/*
* web 安全攻防专题
* ------------------------------------------------------------------------
* xss: 跨站脚本攻击(XSS,Cross-site scripting)*
*
* 1、原理:利用系统漏洞,将具有恶意攻击行为的可执行脚本植入系统,且会自动
* 执行。从而达到破坏的目的
*
* 2、类型:反射型、持久型、DOM 型
*
* 关于预防 xss 攻击,请记住一个神论:永远不要相信前端用户输入的任何信息
*
*
* csrf: 跨站请求伪造(CSRF,Cross-site request forgery)* 攻击者通过各种方法伪造一个请求,模拟用户在系统内的行为活动,从而达到修改用户数据或其他目的
*
* 关于防御:1、尽可能使用 POST 提交请求;2、对请求进行身份认证
*
*
*
* */
/*
* 跨域专题
* ------------------------------------------------------------------------
* 1、什么情况下产生跨域?* http://www.a.com:8000/
* 当协议、主机、端口三者有任一一个不同,视为跨域
*
* 2、跨域出现的原因?* 根本原因是安全问题,即“同源策略”,禁止非同域下的请求产生
* 同源策略涉限制主要有:* a、ajax
* b、dom 操作
* c、本地存储
* 以上这三种操作均有跨域限制
*
* 3、跨域解决方案
* a、jsonp
* 原理:* b、服务端设置响应头,即白名单
* access-control-allow-origin:"*" // 任意域
* access-control-allow-origin:"http://www.a.com" // 只允许 www.a.com 域
* c、nginx 反向代理
*
*
*
*
*
*
* */
/*
* 深浅拷贝专题(深浅只针对引用类型数据展开探讨)* ------------------------------------------------------------------------
* 浅拷贝 - 只会拷贝对象的引用地址(内存地址),新旧对象共享同一内存地址,只有一个对象
* 深拷贝 - 拷贝的是对象自身,而不是内存地址,是一个全新的独立的对象
*
*
*
*
* */
function deepClone(source) {
var target = {}, toString = Object.prototype.toString
for (var prop in source) {if (source.hasOwnProperty(prop)) {if (toString.call(source[prop]) === "[object Object]") {
// 引用类型 - 执行深拷贝
target[prop] = deepClone(source[prop])
} else {
// 浅拷贝
target[prop] = source[prop]
}
}
}
return target
}
/*
* parseInt 专题
* ------------------------------------------------------------------------
* 描述:是一个内置的函数,* 作用:可以把一个字符串转成整形,parseInt 的返回值只有两种情况,a、十进制整数 b、NaN
* 有两个参数
* a、第一个参数表示待转换的字符串(必须是字符串,如果不是字符串,则会发生隐式类型转换
* 然后对转换后的字符串进行截取
*)*
* b、第二个参数表示待转换的字符串的进制 (默认是 10 进制)
* 该值的范围介于 [2,36],如果进制不在此范围内的,一律返回 NaN
*
* 注意:基数如果不是数值,则发生隐式类型转换,如果基数是 NaN,则默认基数是 10
*
* 特别注意,这里的默认进制 10,是有条件的
* 条件 1,必须没有明确指定进制数
* 条件 2,待转换的字符串,不是以 0 或 0x 打头的
*
* 在字符串以 "0" 为开始时旧的浏览器默认使用八进制基数。ECMAScript 5,默认的是十进制的基数。* 如果没有明确指定进度,对于 "0”打头的字符串在“ES5 之前”认为是 8 进制
* 对于 "0”打头的字符串在”ES5 之后“认为是 10 进制
*
* 如果有明确指定数的进制,则以指定的进度为准
*
* var n=parseInt("11",2) // 表示字符串 "11" 是 2 进制的数
* var n=parseInt("11",8) // 表示字符串 "11" 是 8 进制的数
* var n=parseInt("11") // 表示字符串 "11" 是 10 进制的数
*
* // 注意了,radix 是 0、10 均表示 10 进制的数,省略的时候进制可能是 8、10、16
* var n=parseInt("11",0) // 表示字符串 "11" 是 10 进制的数
* var n=parseInt("11",NaN) // 表示字符串 "11" 是 10 进制的数
* var n=parseInt("11",10) // 表示字符串 "11" 是 10 进制的数
*
*
* 使用方法总结:* 1、看参数 1 是否是字符串,如果不是则先转成字符串(如果是非字符串类型,会发生隐式类型转换)* 2、先确定进制
* 3、根据进制截取最终的字符串,如果最终是空字符串,则返回 NaN
*(截取的规则是这样的,从字符串的首位 (如果是 0 的 8 进制数,则从 0 之后开始截取,有点特殊;如果是 0x 的 16 进制数,则从 0x 之后开始截取,有点特殊)
*(如果是空格、+ 会忽略哦,如果是 - 则会输出)开始,依次向后截取,直到“非数字”或者“非指定进制范围内”的字符截止)* 4、转成 10 进制
*
* var num = parseInt(321, 0) //321
* var num = parseInt(321, NaN) //321
* var num = parseInt(321, 2) //NaN
* var num = parseInt("210", 3)//210
* var num = parseInt("329", 6)//20
* var num = parseInt("012", 0)//12
* var num = parseInt("0x12")//18
* var num = parseInt(parseInt,16)//15 这里为什么是 15 呢?因为 parseInt 是一个函数,其实这里的值是 "function(){}"
* var num = parseInt(alert,16)//15
* var num = parseInt(console.log,16)//15
* var num = parseInt(0.000005)//0,直接使用“字面量”表示
* var num = parseInt(0.0000005)//5, 这里返回 5 是因为,小数位后面长度长多 6 位时,采用科学基数法表示,即”5e-7“*
* =====================================================================
* 对于数值型而言,小数位前长度大于 21 或小数位后长度大于 6 时,均使用科学计数法表示
* =====================================================================
*
*
*
* 执行过程分析:(第一个参数命名为参数 1,第二个参数命名为参数 2)* -----------------------------------------------------
* 1、查看参数 1 是否是字符串,如果不是,则会发生隐式类型转换
* 2、确定基数(进制)* a、有明确指定基数,则以指定的基数为准
* b、没有明确指定基数,则以参数 1 进行判断来确定基数,* 首先,参数 1 字符串是以“0”打头,则 es5 以前的版本中,基数为 8,es5 之后的版本中,基数为 10
* 其次,参数 1 字符串是以“0x" 打头,则基数是 16,* 最后,其他情况,基数是 10
* 3、以确定的基数来对参数 1 字符串进行有效性截取(非数字或基数范围外的均视为非法字符)* 4、如果截取的字符串是空字符串,“”则返回 NaN
* 如果是非空有效的字符串,则按照进制规则转换成 10 进制的数
*
* 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
*
* */
/*
* eval 函数专题
* ------------------------------------------------------------------------
* eval 是一个内置的函数
* 作用:当 eval 函数执行时,会把传入的字符串(只能传入原始字符串,不能是字符串包装对象)* 参数当做 JS 代码执行
*
*
* eval("alert(100)") //100
*
*
*
* */
/*
* 事件模型专题
* ------------------------------------------------------------------------
* 什么是事件?事件就是一个约定好的动作,当将来做出了某个动作时,应该做什么事情。*
* 在 JS 中事件模型分为三种:* 1、DOM0(原始事件模型)* 2、DOM2
* 3、IE 事件模型
*
* 1、DOM0 原始事件模型,有两种触发方式:* a、<p onclick="show()">ppppp</p>
* b、document.getElementById(".box").onclick=function(){}
* 优点:所有浏览器都支持
* 缺点:没有事件流(没有冒泡、捕获),只能绑定一次,后面绑定的事件会覆盖前面的
*
* 2、DOM2, 是由 w3c 制定的标准规范,在这个事件模型中,一次事件包含三个阶段
* a、捕获阶段
* b、目标阶段
* c、冒泡阶段
*
* oDiv.addEventListener("click",fn,false)// 绑定事件
* oDiv.removeEventListener("click,fn,false)// 解绑事件
*
*
* 3、IE 事件模型
*
* oDiv.attachEvent("onclick",fn)
* oDiv.detachEvent("onclick",fn)
*
*
*
*
* */
/*
* 函数防抖与函数节流专题
* ------------------------------------------------------------------------
* 无论函数防抖或函数节流,都是为了解决在一个事件内因高频触发动作而带来的性能问题
*
*
*
* */
// 函数防抖 - 代码实现
function debounce(fn, delay) {
var timer
return function () {
var context = this
var args = [].slice.call(arguments)
clearTimeout(timer)
timer = setTimeout(function () {fn.apply(context, args)
}, delay)
}
}
// 函数节流 - 代码实现
function throttle(fn, delay) {
var timer
return function () {
var context = this
var args = [].splice.call(arguments)
if (timer) return
timer = setTimeout(function () {fn.apply(context, args)
clearTimeout(timer)
}, delay)
}
}
/*
* 自定义事件专题
* ------------------------------------------------------------------------
*
*
*
* */
function Event() {
// 事件列表
this.handlers = {}}
Event.prototype = {
constructor: Event,
// 绑定事件
on: function (type, handler) {if (!this.handlers[type]) {this.handlers[type] = []}
this.handlers[type].push(handler)
},
// 解绑事件
off: function (type, handler) {if (this.handlers[type]) {if (this.handlers[type] instanceof Array) {var handlers = this.handlers[type]
for (var i = 0; i < handlers.length; i++) {if (handlers[i] === handler) {handlers.splice(i, 1)
break
}
}
}
}
},
// 触发事件
fire: function (event) {if (!event.target) {event.target = this}
if (this.handlers[event.type] instanceof Array) {var handlers = this.handlers[event.type]
handlers.forEach(handler => {handler(event)
})
}
}
}
function handler() {}
var event = new Event()
event.on("aa", handler)
event.off("aa")
event.fire({type: "aa", message})
/*
* 闭包专题
* ------------------------------------------------------------------------
* 描述
* 在函数内部的标识符被子级执行上下文所使用时,这时在内存中就会形成一个闭包
* 条件
* 函数声明时有嵌套关系,子函数内有
*
*
* */
/*
* 性能优化专题
* ------------------------------------------------------------------------
* 代码层面
* 变量缓存(合理设置缓存)* 多局部变量、少全局变量(减少作用域链或原型链查找的过程)* 减少 DOM 操作 (避免重绘与重排)
* 减少闭包
* 函数防抖节流
* JS 文件放在底部
* 资源层面
* 合并、压缩、精灵图、cdn 加速
*
* */
/*
* JS 数据类型专题
* ------------------------------------------------------------------------
* 在 JS 中数据类型分为,基本数据类型、引用数据类型
* 基本数据类型(特点)* 1、体积固定:值不可变
* 2、体积小
* 3、存放在栈内存中
*
* 引用数据类型(特点)* 1、体积不固定:值可变
* 2、体积大
* 3、存放在堆内存中
*
* 八大数据结构
* 数组
* 堆、栈、队列
* 链表、散列表
* 树
* 图
*
*
* */
/*
* 内存泄漏与内存溢出专题
* ------------------------------------------------------------------------
* 内存泄漏(内存分配出去后,即没有正常使用,又无法收回,那么就认为这块内存泄漏啦)* 正常情况下,在程序执行时,系统会为其分配一定的内存空间,当程序执行完毕后,代码被销毁,* 内存空间会被回收(这里的销毁代码 - 执行上下文被弹出执行栈)* 但是现在出现了这么一个情况,就是程序执行完后,代码没有被销毁,内存无法被回收
* 原本内存有 100M,但是现在有 20M 的内存无法被使用
*
* 哪些情况下回造成内存泄漏?* 1、闭包
* 2、对象互相引用
*
* 内存溢出
* 可使用的内存不足
* 比如说,执行程序需要 50M 内存,但是现在可供使用的内存只有 30M,这么这个时候就发生了
* 内存溢出
*
*
* */
/*
* JS 内存管理专题
* ------------------------------------------------------------------------
* JS 中是如何对内存进行管理的?* 在 JS 中对内存的管理是通过垃圾回收机制来实现的,垃圾回收器会不定时间对已分配出去的且已不再
* 使用的内存空间进行回收。*
* 要求:* 对已分配出去且不再使用的内存一定要及时进行回收,否则会造成内存泄漏
* 注意啦,内存泄漏有两种表现形式,1 是内存根本无法收回,2 是过了很长时间才把内存收回
*
* JS 内存管理是通过垃圾回收技术来实现的,* 垃圾回收器会每隔固定时间对已分配出去且已不再使用的内存进行回收
*
* 如果内存无法收回或者收回耗时过长
* 其中无法收回,肯定会造成内存泄漏
* 长时间才收回的,可能会造成内存泄漏
*
*
* */
/*
*
* A instanceof B
* 在 A 的原型链中是否有 B 对象的原型(注意是 B 的原型,不是 B 自身)*
* A.isPrototypeOf(B)
* 判断 A 是否是 B 的原型
*
* A=Object.create(B)
* 以 B 对象为原型创建一个对象 A,也就是说 B 是 A 的原型
* Object.create(null) instanceof Object //false
* (()=>{}) instanceof Object //true
*
* */
/*
* JS 设计模式
* ------------------------------------------------------------------------
* 构造模式
* 单例模式
* 观察者模式
*
*
*
*
* */
/*
* eval 专题
* ------------------------------------------------------------------------
* eval() 这个函数可以执一段 JS 程序
* 默认情况下其执行上下文是大年 eval 函数所处的
* 执行上下文
* 但是一旦使用了别名,则其执行上下文就是全局
* 执行上下文了
*
* 那么到底哪些是别名呢?* 1、var e=eval
* 2、window.eval
* 3、(eval,eval).call()
* 4、(1,2,3,eval).call()
* 以上这些别名时,其执行上下文均是全局执行上下文
*
* */
eval("console.log(1)")
/*
* with 专题
* ------------------------------------------------------------------------
* 当我们需要访问一个对象的多个属性时,* 我们往往是这样写的,* obj.xx
* ...
* 那么能不能不写这些 obj.xxx 呢?* 答案是:当然可以
* 解决方法:使用 with 劫持一个对象
*
* with 代码块中中程序在查找一个变量时
* 是从 with 劫持的对象开始,即 obj 开始
* 如果找不到,在沿着作用域链查找
* with 代码块之外的程序还是按照原来的
* 方式沿着作用域链查找
*
*
* 大结论:with 是原型链和作用域链的大拼接 (很牛逼啊,居然将两条链子连接起来了)
* 扩展了作用域
*
* 使用了 with 后, 变量查找顺序:对象 ——> 原型链 ——> 作用域链
*
* 不推荐使用,效率低下
*
*
* */
var a=10
var obj={a:20}
var fn=200
Object.setPrototypeOf(obj,{// fn:100})
with(obj){alert(fn)
// with 代码块中的查找机制是 [原型链, 作用域链]
var c=300 // 这里声明了 c
}
alert(a)
/*
* Reflect 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* Proxy 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* WebSocket 专题
* ------------------------------------------------------------------------
*
*
*
* */
const URL = "wss://echo.websocket.org/"
if ('WebSocket' in window) {
// 检测是否支持 WebSocket
const socket = new WebSocket(URL)
// 指定期望返回数据的类型
socket.binaryType = "blob"
if (socket.bufferedAmount == 0) {// 检测剩余数据还有多少}
// 连接成功
socket.onopen = function () {
// 向服务端发送消息
socket.send("Hello")
}
// 接收到服务端返回的消息
socket.onmessage = function (e) {const {data} = e
alert(data)
socket.close()}
// 关闭连接
socket.onclose = function () {console.log("close");
}
// 连接失败
socket.onerror = function () {console.log("error");
}
} else {
// 不支持
console.log("不支持");
}
/*
* Object 专题
* ------------------------------------------------------------------------
* Object.setPrototypeOf(obj,prototype) 操作的是__proto__, 而不是 prototype
*
*
*
* */
/*
* JS 函数声明与函数表达式专题
* ------------------------------------------
* 1、函数声明
* a、必须以 function 关键字打头(福脑垂体欧尼前面不能有任何其他的字符)* b、必须有名称
* 可以预解析
*
*
* 2、函数表达式
* 不是以 function 关键字打头,* 名称可有可无
* 如果有名称,则名称只能在函数体内部可以访问到
* 不可以被预解析
*
*
* 函数声明:function aaa(){}(这种就是函数声明)*
* 函数表达式:* var a = function aaa(){} : 命名函数表达式
* var a = function (){}:匿名函数表达式
* (function aaa(){}) : 表达式
*
* 以下六种都是函数表达式(这六种是独立函数表达式 + 赋值函数表达式)*
* var run=function(){} // 匿名赋值函数表达式
* var run=function Run(){} // 具名赋值函数表达式
*
* +function aaa(){} : 具名独立函数表达式
* -function aaa(){} : 具名独立函数表达式
* !function aaa(){} : 具名独立函数表达式
* ~function aaa(){} : 具名独立函数表达式
* (function aaa(){}) : 具名独立函数表达式
* void function aaa(){} : 具名独立函数表达式
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */
/*
* 专题
* ------------------------------------------------------------------------
*
*
*
* */