赞
踩
作用域就是一个变量可以使用的范围,主要分为全局作用域和函数作用域和块级作用域(es6新增)
全局作用域:Js中最外层的作用域
函数作用域:js通过函数创建的一个独立作用域,函数可以嵌套,所以作用域也可以嵌套
块级作用域:Es6中新增,由大括号包裹,比如:if(){}, for(){} function等
自由变量:在当前作用域被使用,但是没有被定义的变量,被称作自由变量
作用域链:一个变量在当前作用域没有定义,但是被使用了,就会向上级作用域,一层一层依次查找,直至找到为止,如果全局作用域都没有找到这个变量就会报错。这个自由变量查找的过程就是作用域链
注意:函数中的自由变量取决于函数定义的位置,与执行的位置无关。
js在运行之前,会把所有带有var或function的变量与函数提升至当前作用域的最上方
var只提升变量,不提升赋值,而function提升整个函数体
注意:function的优先级比var要高
函数中套了一个函数,内层函数可以访问外层函数中的变量
闭包的分类:
1 函数做为参数被传递
2 函数做为返回值被返出
闭包的运用场景
1 封装对象的私有属性和方法,用于隐藏数据,做一个简单的缓存工具
2 做为回调函数使用
3 利用闭包实现函数的防抖,节流
防抖:例如一个倒计时,被连续点击时,关闭上一个倒计时,重新开启一个新的倒计时
节流:例如一个倒计时,被连续点击时,规定时间内,无论点击多少次,只触发一次
优点:闭包因为长期驻扎在内存中。可以重复使用变量,不会造成变量污染
缺点:闭包会使函数中的变量都被保存在内存中,内存消耗很大,滥用闭包,会造成网页的性能问题,可能会导致内存泄露
解决方法:在退出函数之前,将不使用的变量全部删除
this指向什么值,是在执行的时候确定的,与定义的位置无关,箭头函数除外
常用的调用场景
普通函数 | 指向当前调用它的对象(默认为window) |
构造函数与class类 | 指向当前的实例化对象 |
对象方法的调用 | 指向调用该方法的对象 |
箭头函数 | 指向函数声明所在的对象,与其他的不同,其他的是在调用时,箭头函数则是在声明时 |
定时器(特殊例子) | 指向window(默认), 但是如果内部函数为箭头函数,则指向箭头函数声明时坐在的对象 |
总结:
修改this指向
call | 多个参数, 第一个参数就是要修改的this指向,其他参数是以散落的形式给调用该方法的函数传递参数 Game.call(this , '王者荣耀', '手游') | |
apply | 两个参数 第一个参数就是要修改的this指向,第二个参数是以数组的形式给调用该方法的函数传递参数 | |
bind |
|
浏览器的js具有自动垃圾回收机制(GC),执行环境会管理代码在执行中所使用的内存,垃圾回收器会定期寻找不再使用的变量,释放其内存,垃圾回收器会按照时间间隔周期性的执行。
变量的死亡
全局作用域内的变量,会在关闭浏览器关闭页面时结束,被垃圾回收期回收
函数级与块级作用域内的变量,只有在函数执行的过程中存在,函数执行完毕,垃圾回收器回收释放
闭包内,因为内部函数使用外部函数变量的原因,它内部的变量,永远不会结束、
判别变量是否还有用的两种方式:
1. 标记清除(常用)
垃圾回收器在运行的时候会给存储在内存中的所有变量都加上标记。当一个变量进入环境时,就将这个变量标记为“进入环境”,而当变量离开环境时,则将其标记为“离开环境”。垃圾收集器下次运行时,就会把所有标为离开环境的变量回收释放。
-
- function test(){
- var a = 10 ;
- var b = 20 ;
- }
- // 在调用该函数时,内部的变量会标记为进入环境
- test();
- // 函数执行完毕之后 a、b又被标离开环境,被回收。
2. 引用计数
跟踪记录每个值别引用的次数,当声明了一个变量,并将一个引用类型的值赋给该变量时,那这个值的引用次数就是1,而这个值再被赋值给另一个变量,那这个值的引用次数+1,相反,如果包含这个值的变量,获取了另外的值,那这个值的引用次数-1,当这个值的引用次数为0时,垃圾回收器下次运行时,就会把这个值回收释放。
-
- function test() {
- var a = {}; // a指向对象的引用次数为1
- var b = a; // a指向对象的引用次数加1,为2
- var c = a; // a指向对象的引用次数再加1,为3
- var b = {}; // a指向对象的引用次数减1,为2
- }
1. 循环引用
一个DOM对象被一个Javascript对象引用,又引用同一个或其它的Javascript对象,这个DOM对象可能会引发内存泄露。将不会在脚本停止的时候被垃圾回收器回收。要想破坏循环引用,赋值为null即可
2. 闭包
在闭包中引入闭包外部的变量时,当闭包结束时此对象无法被垃圾回收
3. DOM泄露
当原有的DOM被移除时,子结点引用没有被移除则无法回收
js的机制是先执行同步事件,再执行异步事件
异步事件又分为了宏任务与微任务,微任务的执行时间要比宏任务早
宏任务:setTimeout setInterval Ajax DOM事件
微任务:promise async/await
异步和单线程是相辅相成的,js是一门单线程脚本语言,所以需要异步来辅助
异步与同步的区别
同步会阻塞代码的执行,而异步不会
JS的任务运行顺序
1 将所有的任务放进执行线
2 分出同步任务还是异步任务
3 将同步任务放入主线程,进行执行
4 将异步任务放入Event Table并注册函数,放入事件队列中
5 在同步任务完成后,再将任务队列的放入主线程进行执行
6 异步先执行微任务,再执行宏任务
注意事项
1 在异步事件中,遇到其他宏任务,将其放进下一个事件队列
2 swite异步代码同步执行,但是会把后面的代码,变成一个微任务
基本数据类型(值类型): Number、String、Boolean、Undefined、Null、Symbol(es6新增独一无二的值) 和 BigInt(es10新增);
引用数据类型: Object。包含Object、Array、 function、Date、RegExp。
typeof、instanceof、constructor、Object.prototype.toString.call()、jquery.type()
for···in和for···of的区别
①从遍历数组角度来说,for···in遍历出来的是key(即下标),for···of遍历出来的是value(即数组的值);
②从遍历字符串的角度来说,同数组一样。
③从遍历对象的角度来说,for···in会遍历出来的为对象的key,但for···of会直接报错。
④如果要使用for…of遍历普通对象,需要配合Object.keys()一起使用。
null和undefined区别
在 if 语句中 null 和 undefined 都会转为false两者用相等运算符比较也是相等
1.null表示没有对象,可能将来要赋值一个对象,即该处不应该有值
1 作为函数的参数,表示该函数的参数不是对象
2 作为对象原型链的终点
2 undefined表示缺少值,即此处应该有值,但没有定义
1 定义了形参,没有传实参,显示undefined
2 对象属性名不存在时,显示undefined
3 函数没有写返回值,即没有写return,拿到的是undefined
4 写了return,但没有赋值,拿到的是undefined
设计模式
一、单例模式
1. 定义
保证一个类仅有一个实例,并提供一个访问它的全局访问点
2. 核心
确保只有一个实例,并提供全局访问
3. 实现
在vue脚手架项目开发中,我们需要对axios进行请求拦截,响应拦截,多次调用封装好的axios实例也仅设置一次,封装后的axios就是要一个单例
二、发布者、订阅者模式
vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
js的事件
DOM事件的三种级别
DOM 0级事件
DOM 0级时间分两种,一是直接在标签内直接添加执行语句,二是定义执行函数
<input type="text" id="test">
<input type="button" value="button" οnclick="alert(document.getElementById('test').value)">
<script>
document.getElementById('button').οnclick=function(){
alert(document.getElementById('test').value);
}
</script>
DOM 2级事件
2级事件有3个参数,分别为 事件名称,执行函数,指定冒泡还是捕获,默认是false,冒泡。
element.addEventListener('click',function(){},false)
DOM 3级事件
同DOM2级一样,只不过添加了更多的事件类型,鼠标事件、键盘事件
element.addEventListener('keyup',function(){},false)
DOM的事件类型
事件类型分两种:事件捕获、事件冒泡。
事件捕获就是由外往内,从事件发生的顶点window开始,之后是document对象,逐级往下查找,一直到目标元素。
事件冒泡就是由内往外,从具体的目标节点元素触发,逐级向上传递,直到根节点window。
DOM事件的事件流(事件传播)
事件流就是,事件的传播过程。
DOM完整的事件流包括三个阶段:事件捕获阶段、目标阶段和事件冒泡阶段。
事件通过捕获到达目标元素,这个时候就是目标阶段。从目标节点元素将事件上传到根节点的过程就是第三个阶段,冒泡阶段
自定义事件
我们也可以通过 new Event()自定义事件
var eve = new Event('test'); //通过new Event 创建事件
dom.addEventListener('test', function () { //注册事件
console.log('test dispatch');
});
setTimeout(function () {
dom.dispatchEvent(eve); //触发事件
}, 1000);
解决跨域
什么是跨域
理解跨域的概念:协议、域名、端口都相同才同域,否则都是跨域
跨域就是指浏览器不允许当前页面的所在源,去请求另一个源的数据
JSONP原理
出于安全考虑,服务器不允许 ajax 跨域获取数据,但是可以跨域获取文件内容,所以基于这一点,可以动态创建 script 标签,使用标签的 src 属性访问 js 文件的形式获取 js 脚本,并且这个 js 脚本中的内容是函数调用,该函数调用的参数是服务器返回的数据,为了获取这里的参数数据,需要事先在页面中定义回调函数,在回调函数中处理服务器返回的数据,这就是解决跨域问题的jsonp原理。
脚手架解决跨域
在脚手架中,创建 vue.congif.js 文件,里面的 devServer 是进行开发环境的服务器配置的,里面有proxy是用来进行代理的转发,在proxy里的 target 设置转发的网址
因为跨域的问题,axios是无法请求网址数据的,但是浏览器可以,所以,应用代理转发请求数据到我们设置的网址中,而axios请求该网址,相当于一个中间商进行了一次代理
let、var、const区别
Var是块级作用域,值可以更改,多次定义会被顶替,拥有变量提升特性,可以不赋值
Let 函数级作用域,值可以更改,不能多次定义,无法变量提升,可以不赋值
Const 函数级作用域,是一个常量,值不能为空,一经定义无法更改,无法变量提升,必须赋值
注意:const如果定义的是一个数组或者对象,它的值就是一个指针,数组或对象里面的值是可以更改的,并不影响这个指针
es6解构赋值
es6可以根据一定的规则,从数组或变量中提取值赋给变量,字符串也可以直接进行结构赋值,无论对象还是数组,两边的 = 数据类型和数据结构都必须保持一致
解构
数组的解构:数组的结构赋值是按照索引值一一对应的,如果多层嵌套,结构也必须保持一致,不想要的数据可以在解构时用,隔开 空格表示
字符串的解构遵循数组的方式,因为它同样有下标和length
对象的解构:对象的解构按照key值来对应 {key}
//数组结构
var a, b, rest;
[a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20
//对象解构
({ a, b } = { a: 10, b: 20 });
console.log(a); // 10
console.log(b); // 20
// ...rest 解构数组
[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a); // 10
console.log(b); // 20
console.log(rest); // [30, 40, 50]
// ...rest 解构对象(最新)
({a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40});
console.log(a); // 10
console.log(b); // 20
console.log(rest); // {c: 30, d: 40}
//解析一个从函数返回
function f() {
return [1, 2];
}
var a, b;
[a, b] = f();
console.log(a); // 1
console.log(b); // 2
解构的默认值
数组,对象,字符串都是一样的,默认值就是a = 值 ,默认值只有在没有数据,也就是undefined时生效
解构赋值的rest参数
rest会将剩余的所有数据赋值给rest,必须放在最后,...rest
箭头函数与普通函数的区别
普通函数会遇到this作用域问题,ES6新建箭头函数
箭头函数无法作为构造函数使用,无法实例化,
箭头函数this指向她所在的作用域,
箭头函数本身没有arguments参数
箭头函数不能通过call()、apply()、bind()方法直接修改它的this指向
箭头函数没有原型属性
promise使用及实现
promise是es6提出的一种异步编程的解决方案,接受两个函数做为参数,从语法上说,promise 是一个对象,从它可以获取异步操作的的最终状态(成功或失败),本质上是一个构造函数,
promise的状态
promise的状态不受外部影响,一经改变就代表执行结束,无法再进行更改
pending 初始状态 fulfilled 成功状态 rejected 失败状态
promise的参数
resolve的作用是将promise的状态从进行中pending变为已完成fullfilled,并将成功信息返出
reject的作用是将promise的状态从进行中pending变为已失败rejected,并将失败信息返出
promise的状态一经改变就代表执行结束
promise一些api
.then()获取promise的结果
.catch()来获取失败时返出的错误信息
Promise.all( ) 接受多个promise的实例做为参数,参数必须是一个数组,promise都执行成功后,返回的是执行后的结果的一个数组,如果有一个失败了,返回的是第一个失败的返回值
Promise.race( ) 接受多个promise的实例做为参数,其中一个promise完成时执行,返回结果是第一个完成的promise的返回数据
名词约定
promise(首字母小写)对象指的是“Promise实例对象”
Promise首字母大写且单数形式,表示“Promise构造函数”
Promises首字母大写且复数形式,用于指代“Promises规范”
async/await
特点
asayc的用法,它作为一个关键字放到函数前面,这样普通函数就变为了异步函数
异步async函数调用,跟普通函数的使用方式一样
异步async函数返回一个promise对象
async函数配合await关键字使用,await异步代码同步执行,但是后面的代码将会被阻塞,变为一个异步微任务,
优点
1.方便级联调用:即调用依次发生的场景;
2.同步代码编写方式:更符合代码编写习惯;
3.多个参数传递: Promise的then函数只能传递一个参数,async/await没有这个限制,可以定义块级变量传递数据
4.同步代码和异步代码可以一起编写: async/await整个书写习惯都是同步的,不需要纠结同步和异步的区别,当然,异步过程需要包装成一个Promise对象放在await关键字后面;
5.sync/await是对Promise的优化:不过在写代码时,Promise本身的API出现得很少,很接近同步代码的写法;
Es6中新的数据类型symbol
Symbol 值通过Symbol函数生成。对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol
凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
注意,Symbol函数前不能使用new命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。
当url输入到页面发生了什么
浏览器的地址栏输入URL并按下回车,
查找当前的URL是否存在缓存,并比较缓存是否过期,
DNS解析URL对应的IP,
根据IP建立TCP连接(三次握手),
HTTP发起请求,服务器处理请求,浏览器接收HTTP响应,
渲染页面,构建DOM树,
关闭TCP连接(四次挥手)。
三次握手和四次挥手
三次握手:
第一次:建立连接时,客户端发送一个SYN包到服务器请求链接
第二次:服务器收到SYN包,并确认,同时也发送一个SYN+ACK包到客户端
第三次:客户端收到服务器的SYN+ACK包,向服务器发送最终的确认ACK包,发送完毕,客户端和服务端连接成功,完成三次握手
四次挥手:
第一次:浏览器发送完数据后,发送断开连接的FIN请求
第二次:服务器发送ACK包到客户端,确认浏览器的断开请求,并做好准备
第三次:服务器最终向客户端确认是否断开连接
第四次:客户端确认,断开服务器
http和https的区别
1、HTTP是超文本传输协议,信息是明文传输,HTTPS是具有安全性的SSL加密传输协议。
2、HTTPS协议需要ca申请证书,一般免费证书少,因而需要一定费用。
3、HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样。前者是80,后者是443。
4、HTTP连接是无状态的,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,安全性高于HTTP协议。
使用基于token的登录流程
客户端使用用户名跟密码请求登录
服务端收到请求,去验证用户名与密码
验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
Get和post
Get是向服务器请求数据,post是向服务器提交数据
Get在数据传输时可见,post不可见
Get传输数据量小,post比较大
Get执行效率却比Post方法好
Get是form提交的默认方法。
get推荐使用在查询信息时的使用,post适用于登录,注册等带有信息的请求
web安全及防护
1.XSS攻击原理:
攻击者往Web页面里插入恶意 html标签或者javascript代码。用来窃取cookie中的用户信息
解决:对一些输入的字符进行过滤,尽量采用post表单提交的方式。
2.CSRF攻击(跨站请求伪造)
登录受信任的网站A,并在本地生成Cookie,在不登出A的情况下,携带cookie去访问危险网站B/
解决:通过验证码的方式解决
3.SQL注入攻击
就是通过吧SQL命令插入到Web表单递交或输入域名,最终达到欺骗服务器执行恶意的SQL命令。
解决:表单输入时通过正则表达式将一些特殊字符进行转换
html和XML
区别
html被称为超文本标记语言,是一种描述性语言,是构成网页文档的主要语言,它是由很多的标签组成
xml 即可扩展标记语言,是Internet环境中跨平台的、依赖于内容的技术,是当前处理结构化文档信息的有力工具,满足了Web内容发布与交换的需要,适合作为各种存储与共享的通用平台。
共同点
都可以通过DOM 来访问。都可以通过CSS来改变外观。
html和xml 都是标记语言,都是基于文本编辑和修改的。
xml不是要来取代html的,是对html的补充,用来与html协同工作的语言,基于上面这些优势,xml将来成为所有的数据处理和数据传输的常用工具非常可观。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。