一、js的数据类型
值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol,大数值类型(BigInt)
引用数据类型:对象(Object)、数组(Array)、函数(Function)、日期(Date)。
注:Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值(标识符)。
二、什么是函数
JS函数的概念
函数就是把特定功能的代码抽取出来,使之成为程序中的一个独立实体。
- 函数的作用
正如函数的概念, 我们可以根据需要, 将特定的功能用函数来包裹(封装)
- 使用函数的好处
1, 函数可以在同一个程序或其他程序中多次重复使用(通过函数名调用)2, 使程序变得更简短而清晰 , 提高可读性3, 有利于程序维护
三、本地对象、内置对象和宿主对象
1.内置
对象
js中的内部对象包括Array、Boolean、Date、Function、Global、Math、Number、Object、>RegExp、String以及各种错误类对象,包括Error、EvalError、RangeError、ReferenceError、>SyntaxError和TypeError。
其中Global和Math这两个对象又被称为“内置对象”,这两个对象在脚本程序初始化时被创建,不必实例化这两个对象。
2.宿主对象
宿主对象就是执行JS脚本的环境提供的对象。对于嵌入到网页中的JS来说,其宿主对象就是浏览器提供的对象,所以又称为浏览器对象,如IE、Firefox等浏览器提供的对象。不同的浏览器提供的宿主对象可能不同,即使提供的对象相同,其实现方式也大相径庭!这会带来浏览器兼容问题,增加开发难度。浏览器对象有很多,如Window和Document等等。
3.自定义对象
顾名思义,就是开发人员自己定义的对象。JS允许使用自定义对象,使JS应用及功能得到扩充
四、数组(Array)
1.基本方法
push() 从后面添加元素,返回值为添加完后的数组的长度
pop() 从后面删除元素,只能是一个,返回值是删除的元素
shift() 从前面删除元素,只能删除一个 返回值是删除的元素
unshift() 从前面添加元素, 返回值是添加完后的数组的长度
splice(i,n) 删除从i(索引值)开始之后的那个元素。返回值是删除的元素
concat() 连接两个数组 返回值为连接后的新数组
split() 将字符串转化为数组
sort() 将数组进行排序,默认根据ASCII码比较,返回值是排好的数组
reverse() 将数组反转,返回值是反转后的数组
slice(start,end) 切去索引值start到索引值end的数组,不包含end索引的值,返回值是切出来的数组
indexOf() 查找某个元素的索引值,若有重复的,则返回第一个查到的索引值若不存在,则返回 -1
2.高阶函数(1)
forEach(callback) 遍历数组,无return 即使有return,也不会返回任何值,并且会影响原来的数组
map(callback) 映射数组(遍历数组),有return 返回一个新数组 。
注意:`forEach()和map()的区别`
> 1. arr.forEach()是和for循环一样,是代替for。arr.map()是修改数组其中的数据,并返回新的数据。
>
>
> 2. arr.forEach() 没有return arr.map() 有return
3.高阶函数(2)
filter(callback) 过滤数组,返回一个满足要求的数组
every(callback) 依据判断条件,数组的元素是否全满足,若满足则返回ture
some() 依据判断条件,数组的元素是否有一个满足,若有一个满足则返回ture
reduce(callback, initialValue) 迭代数组的所有项,累加器,数组中的每个值(从左到右)合并,最终计算为一个值
lastIndexOf() 和arr.indexOf()的功能一样,不同的是从后往前查找
Array.from() 将伪数组变成数组,就是只要有length的就可以转成数组。 ---es6
Array.of() 将一组值转换成数组,类似于声明数组 ---es6
find(callback) 找到第一个符合条件的数组成员
findIndex(callback) 找到第一个符合条件的数组成员的索引值
fill(target, start, end) 使用给定的值,填充一个数组
includes() 判断数中是否包含给定的值
keys() 遍历数组的键名
values() 遍历数组键值
entries() 遍历数组的键名和键值
五、字符串(String)
字符串的恒定性
字符串的方法修改字符,不会改变原来的字符串,叫做恒定性
字符串的方法
charAt(): 返回指定下标位置的字符。如果index不在0-str.length(不包含str.length)之间,返回空字符串。
charCodeAt(): 返回指定下标位置的字符的unicode编码,这个返回值是 0 - 65535 之间的整数。
indexOf(): 返回某个指定的子字符串在字符串中第一次出现的位置
toLowerCase()把字符串转为小写,返回新的字符串。
toUpperCase(): 把字符串转为大写,返回新的字符串。
lastIndexOf(): 返回某个指定的子字符串在字符串中最后出现的位置。
slice(): 返回字符串中提取的子字符串。
substring(): 提取字符串中介于两个指定下标之间的字符。
split(): 把字符串分割成字符串数组。
substr(): 返回从指定下标开始指定长度的的子字符串
replace(): 在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
match(): 返回所有查找的关键字内容的数组。
六、浏览器渲染页面的原理及流程
浏览器将域名通过网络通信从服务器拿到html文件后,如何渲染页面呢?
1.根据html文件构建DOM树和CSSOM树。构建DOM树期间,如果遇到JS,阻塞DOM树及CSSOM树的构建,优先加载JS文件,加载完毕,再继续构建DOM树及CSSOM树。2.构建渲染树(Render Tree)。3.页面的重绘(repaint)与重排(reflow,也有称回流)。页面渲染完成后,若JS操作了DOM节点,根据JS对DOM操作动作的大小,浏览器对页面进行重绘或是回流
七、重绘和回流(repaint&reflow)
当Render Tree中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。
导致回流的操作:
1、页面首次渲染
2、浏览器窗口大小发生改变
3、元素尺寸或位置发生改变
4、元素内容变化(文字数量或图片大小改变而引起的计算值宽度和高度改变)
5、元素字体大小变化
6、添加或者删除可见的DOM元素
7、激活CSS伪类(例如::hover)
8、查询某些属性或调用某些方法
9、offsetWidth,width,clientWidth,scrollTop/scrollHeight的计算,会使浏览器将渐进回流队列Flush,立即执行回流。
当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。
回流必定会发生重绘,重绘不一定会引发回流。
八、如何避免重绘和回流?
1.避免使用table布局,可能很小的一个小改动会造成整个table的重新布局
2.尽可能在DOM树的最末端改变class。
3.避免设置多层内联样式。
4.将动画效果应用到position属性为absolute或fixed的元素上。
5.动画实现的速度的选择,动画速度越快,回流次数越多,也可以选择使用requestAnimationFrame
6.避免使用CSS表达式(例如:calc())
7.使用transform替代top
8.使用visibility替换display: none,因为前者只会引起重绘,后者会引发回流(改变了布局)
将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点
js:
1.避免频繁操作样式,最好一次性重写style属性,cssText,或者将样式列表定义为class并一次性更改class属性。
2.避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。
3.也可以先为元素设置display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。
4.避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
5.对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。
九、什么是闭包(Closure)
闭包是这样一种机制:
函数嵌套函数,内部函数可以引用外部函数的参数和变量,参数和变量不会被垃圾回收机制所收回.
闭包的好处:
- 可以让一个变量长期驻扎在内存当中不被释放
- 避免全局变量的污染, 和全局变量不同, 闭包中的变量无法被外部使用
- 私有成员的存在, 无法被外部调用, 只可以自己内部使用
闭包的用途
1.实现缓存
2.存储值与避免变量全局污染
使用闭包的注意点
(1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。(2)闭包会在父函数外部,改变父函数内部变量的值。
十、垃圾回收机制(GC)
JS引擎会在一定的时间间隔来自动对内存进行回收(把内存释放)
JS垃圾回收机制有两种: 1, 标记清除, 2, 引用计数
1, 标记清除: js会对变量做一个标记Yes or No的标签以供js引擎来处理, 当变量在某个环境下被使用则标记为yes, 当超出该环境(可以理解为超出作用域)则标记为no, js引擎会在一定时间间隔来进行扫描, 会对有no标签的变量进行释放(将该变量所占的内存释放掉)
2, 引用计数: 对于js中引用类型的变量, 采用引用计数的内存回收机制, 当一个引用类型的变量赋值给另一个变量时, 引用计数会+1, 而当其中有一个变量不再等于值时, 引用计数会-1, 如果引用计数为0, 则js引擎会将其释放掉
十一、什么是回调函数(callback)
回调函数也是一种高阶函数,把一个函数当做另外一个函数的参数,在另外一个函数内部被执行和传递参数
好处:
1.解决异步
2.对函数进行功能扩展
缺点:
1.容易造成回调地狱,回调地狱不方便维护与理解,
2.解决方案使用 promise + async + await
十二、什么是ajax
AJAX (阿贾克斯 Asynchronous Javascript And Xml ) 异步JavaScript和XML,是指一种创建交互式网页应用的网页开发技术, 可以访问服务器数据的局部刷新的技术
核心对象: XMLHttpRequest
ajax的异步如何获取到数据?
使用
onreadystatechange
事件(事件队列event loop的宏任务),并结合callback
回调函数
ajax的同步,发送请求时会占据 (thread main)主线程,造成阻塞,不推荐使用
十三、get请求与post请求的区别?
GET在浏览器回退时是无害的,而POST会再次提交请求。GET请求会被浏览器主动cache,而POST不会,除非手动设置。GET请求只能进行url编码,而POST支持多种编码(文字,图片,电影..)方式。GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。GET请求在URL中传送的参数是有长度限制的,而POST么有。对参数的数据类型,GET只接受ASCII字符,而POST没有限制。GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。GET参数通过URL传递,POST放在Request body中。GET产生的URL地址可以被Bookmark,而POST不可以。
注意:GET产生一个TCP数据包;POST产生两个TCP数据包。Firefox就只发送一次
十四、HTTP协议
1.什么是http协议
超文本传输协议HyperText Transfer Protocol
它是基于TCP协议的应用层传输协议,
简单来说就是客户端和服务端进行数据传输的一种规则
2.http 协议一共有五大特点:
HTTP 是一个属于应用层的面向对象的协议有五大特点
1.支持客户/服务器模式。2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种 方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type(Content-Type是HTTP包中用来表示内容类型的标识)加以标记。4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开式连接。采用这种方式可以节省传输时间。5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
3.请求报文(request)
1.请求行 [请求方式 url地址 协议(1.0/1.1/2.0) ]
2.请求头部 [content-type,cookie]
3.请求体 [数据]</pre>
![image](https://upload-images.jianshu.io/upload_images/25045198-9a33be8503a5b64d.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![image](https://upload-images.jianshu.io/upload_images/25045198-4c9df6f724af2b89.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
4.响应报文 (response)
1.状态行 [协议, 状态码,短语]
2.响应头 [content-Type,...]
3.响应体 [数据]</pre>
![image](https://upload-images.jianshu.io/upload_images/25045198-14e7dccde95adf2f.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![image](https://upload-images.jianshu.io/upload_images/25045198-7c7a98597a8da1f6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
十五、Promise
回调函数是用来解决异步或对函数进行功能扩展,如果滥用回调函数的嵌套,就会形参回调地狱 回调地狱,不方便维护与代码的理解,就可以采用Promise. promsie是一个类,需要被实例化
promsie 有三种状态
1.pending 等待 默认是 等待
2.fulfilled 完成
3.rejected 拒绝
它们是不可以逆</pre>
promsie的原型方法
then() 里面有2个函数,第1个函数取resolve的结果,第2个参数取reject的结果 catch() 捕获 reject的结果 finally() 只要执行resolve或reject后,都会执行finally
promise的静态方法
Promise.all() ,all方法里需要填入一个数组,数组里必须都是支持promise的方法,所有的结果
Promise.race(),race方法里需要填入一个数组,谁先执行,就只取谁的结果
Promise.resolve() 只执成功,并返回一个新的promise对象
Promise.reject() 只执失败,并返回一个新的promise对象
ES7 async await
await关键字后面必须接promise对象,有await关键字的地方,必须是一个async 异步函数
它能解决,把异步像同步一样的被调用
十六、同源策略
同源策略是一种ajax的安全机制,
如果出现 协议,域名,端口,三者不统一,就会产生跨域
http://www.baidu.com //协议不同,跨域
http://www.baidu.com
http://mail.baidu.com 二级域名
http://aaa.bbb.baidu.com 三级域名 域名不同,跨域
http://www.baidu.com:8080
http://www.baidu.com:5500 端口不一致,跨域
如何解决跨域(CORS)呢?
目前常见的方案
在后端的响应头加上一句
Access-Control-Allow-Origin:*
,这里的*表示所有请求,都可以访问该服务-
采用非官方的跨域方案 ,JSONP, 它算不上真正ajax请求,它只能算get请求,因为它是利用了带
src
属性的script
,不受限制的访问外部资源,再又结合callback
回调函数获取数据.还要和后端配合使用
前端使用webpack模块中的server proxy ,实现服务器端代理,来解决跨域
十七、什么是xss攻击?
十八、JSONP和JSON的区别 ?
jsonp 是一种非官方的跨域解决方案,它是利用script的src,不受限制的访问外部资源,并结合callback拿到数据
它并不是真正的ajax,它是一个get请求,更加适合做查询.
json 是一种轻量级的数据结构,能跨平台进行网络传输,能做配置文件.
xml 可扩展性标记语言,是一种重量级的数据格式,也能做跨平台进行网络传输和做配置文件.
十九、什么是oop(面向对象)
oop是一种编程思想,又叫做面向对象编程
它有三大特性
封装 将相同的属性和方法提取成一个类
继承 子类拥有父类的属性和方法
多态
重写 子类重写父类的属性和方法
重载 在同一个类中,同名不同参数 js没有重载
补充: css3大特性
层叠性,继承性,优先级(特殊性)
二十、继承
1\. 对象冒充继承 使用 bind,call,apply
缺点:不能继承原型上的属性和方法
2\. 原型链继承
缺点:不能让构造函数的属性,初始化
3\. 组合继承 (对象冒充+原型继承)
缺点:原型中会有多余的属性,并且是undefined
4\. ES6的class和extends继承
5\. 寄生组合继承 Object.create(base.prototype);
二十一、递归
1.什么是递归?
函数自己调用自己,要有零界点(结束条件)
2.递归能做什么?
循环的能做的事,递归都能实现
3.递归的使用场景
1. 快速排序使用递归
2. nodejs磁盘文件的遍历,使用递归
3. 管理系统的权限菜单栏(n级菜单栏)
4. 对象的深拷贝
二十二、节流(throttle)与防抖(debounce)
防抖:任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行
触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
// 1、防抖功能函数,接受传参
function debounce(fn,delay==600) {
// 2、创建一个标记用来存放定时器的返回值
let timeout = null;
return function() {
// 3、每次当用户点击/输入的时候,把前一个定时器清除
clearTimeout(timeout);
// 4、然后创建一个新的 setTimeout,
// 这样就能保证点击按钮后的 interval 间隔内
// 如果用户还点击了的话,就不会执行 fn 函数
timeout = setTimeout(() => {
fn.call(this, arguments);
}, delay);
};
}
节流:指定时间间隔内只会执行一次任务。
高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率
function throttle(fn,delay=600) {
// 1、通过闭包保存一个标记
let canRun = true;
return function() {
// 2、在函数开头判断标志是否为 true,不为 true 则中断函数
if(!canRun) {
return;
}
// 3、将 canRun 设置为 false,防止执行之前再被执行
canRun = false;
// 4、定时器
setTimeout( () => {
fn.call(this, arguments);
// 5、执行完事件(比如调用完接口)之后,重新将这个标志设置为 true
canRun = true;
}, delay);
};
}</pre>
节流和防抖的共同点,都是减少执行频率.
函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,
而函数防抖只是在最后一次事件后才触发一次函数
二十三 、defer和async的区别
<script src="./async1.js" async defer></script>
defer:在HTML解析完之后才会执行。如果是多个,则按照加载的顺序依次执行。
async:在加载完之后立即执行。如果是多个,执行顺序和加载顺序无关
二十四、前端性能优化
-
减少 HTTP 请求数量
-
基本原理:在浏览器与服务器进行通信时,主要是通过 HTTP 进行通信。浏览器与服务器需要经过三次握手,每次握手需要花费大量时间。而且不同浏览器对资源文件并发请求数量有限(不同浏览器允许并发数),一旦 HTTP 请求数量达到一定数量,资源请求就存在等待状态,这是很致命的,因此减少 HTTP 的请求数量可以很大程度上对网站性能进行优化。
CSS Sprites:国内俗称 CSS 精灵,这是将多张图片合并成一张图片达到减少 HTTP 请求的一种解决方案,可以通过 CSS background 属性来访问图片内容。这种方案同时还可以减少图片总字节数,节省命名词汇量(由命名多张图片文件变成一张,哈哈哈)。
合并 CSS 和 JS 文件:现在前端有很多工程化打包工具,如:grunt、gulp、webpack等。为了减少 HTTP 请求数量,可以通过这些工具再发布前将多个 CSS 或者 多个 JS 合并成一个文件。
采用 lazyLoad:俗称懒加载,可以控制网页上的内容在一开始无需加载,不需要发请求,等到用户操作真正需要的时候立即加载出内容。这样就控制了网页资源一次性请求数量。
-
-
控制资源文件加载优先级
-
基本原理:说到这里就需要知道浏览器加载 HTML 内容的原理,浏览器在加载 HTML 内容时,是将 HTML 内容从上至下依次解析,解析到 link 或者 script 标签就会加载 href 或者 src 对应链接内容,为了第一时间展示页面给用户,就需要将 CSS 提前加载,不要受 JS 加载影响。
- 遵循原则:主要文件放在 head 内部,次要文件放在 body 底部。一般情况下都是 CSS 在头部,JS 在底部。
-
-
利用浏览器缓存
-
基本原理:浏览器缓存分强缓存和协商缓存,他们是将网络资源存储在本地,等待下次请求该资源时,如果命中就不需要到服务器重新请求该资源,直接在本地读取该资源。
强缓存:在 web 服务器返回的响应中添加 Expires 和 Cache-Control Header。
协商缓存:通过【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】这两对 Header 分别管理。
-
-
使用 CDN
- 基本原理:CDN的全称是Content Delivery Network,即内容分发网络。
-
减少重排(Reflow)
-
基本原理:重排是 DOM 的变化影响到了元素的几何属性(宽和高),浏览器会重新计算元素的几何属性,会使渲染树中受到影响的部分失效,浏览器会验证 DOM 树上的所有其它结点的 visibility 属性,这也是 Reflow 低效的原因。如果 Reflow 的过于频繁,CPU 使用率就会急剧上升。
- 减少 Reflow,如果需要在 DOM 操作时添加样式,尽量使用 增加 class 属性,而不是通过 style 操作样式。
-
减少 DOM 操作
使用createDocumentFragment
- 图标使用 IconFont 替换
[https://www.jianshu.com/p/d9c20eafa67e](https://www.jianshu.com/p/d9c20eafa67e) 网页性能优化
[https://segmentfault.com/a/1190000017329980](https://segmentfault.com/a/1190000017329980) 你真的了解回流和重绘吗
二十五 、值类型和引用类型的区别
【值类型】
1.占用空间固定,保存在栈中,在当前环境执行结束时销毁2.保存和赋值是值的本身3.可以使用typeof检测数据类型4.基本类型数据是值类型
【引用类型】
1.占用空间不固定,保存在堆中,只有在引用的它的变量不在时,会被垃圾回收机制回收。 (引用变量存储在栈中的是指向堆中的数组或者对象的地址 )2.保存与复制的是指向对象的一个指针3.使用instanceof检测数据类型4.使用new()方法构造出的对象是引用型
二十六 、什么是cookie?
基于http协议的一种本地'存储'技术 (它就相当于钱包)
document.cookie="username=itzan; expires=有效时间 GMT; path=/";domain=;secure;
它的特点:
1.基于http协议 2.它会随着请求携带到服务器3.只能存储4k左右4.能跨域(设置domain),默认不可以 5.容易被伪造,不安全,会造成 xss攻击 (站点伪造)
它的使用场景:
1.免登录 2.购物车 3.简单的存储,非铭感数据
http协议
常见于 浏览器与服务器的通信,它是属于 应用层 (应用程序) http 默认的端口是80 http协议的特点 短连接(断开式) 浏览器向服务器发送请求,服务器接受,并响应 无状态 不知道是谁访问了服务器,
- (cookie+session)
- token 凭证
二十七、cookie 、sessionStorage与localStorage的区别
特性 | sessionStorage | localStorage | |
---|---|---|---|
数据的生命期 | 一般由服务器生成,可设置失效时间。如果在浏览器端生成Cookie,默认是关闭浏览器后失效 | 仅在当前会话下有效,关闭页面或浏览器后被清除 | 除非被清除,否则永久保存 |
存放数据大小 | 4K左右 | 一般为5MB | 一般为5MB |
与服务器端通信 | 每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 | 仅在客户端(即浏览器)中保存,不参与和服务器的通信 | 仅在客户端(即浏览器)中保存,不参与和服务器的通信 |
易用性 | 需要程序员自己封装,源生的Cookie接口不友好 | 源生接口可以接受,亦可再次封装来对Object和Array有更好的支持 | 源生接口可以接受,亦可再次封装来对Object和Array有更好的支持 |
WebStorage(sessionStorage与localStorage)提供了一些方法,数据操作比cookie方便;
1).setItem (key, value) —— 保存数据,以键值对的方式储存信息。2).getItem (key) —— 获取数据,将键值传入,即可获取到对应的value值。3).removeItem (key) —— 删除单个数据,根据键值移除对应的信息。4).clear () —— 删除所有的数据5).key (index) —— 获取某个索引的key