一、Var、Let与Const的区别
1、var 可以跨块访问,let、const不行,只在所声明的代码块内有效。都不能跨函数访问
2、var会变量提升,let、const必须遵守“先声明,后使用”的规则,否则会报错
3、var可以重复声明变量,覆盖之前的,let、const不允许在统一作用域内重复声明同一个变量
4、const声明一个常量,使用时必须初始化并且不能修改。但是const声明的对象属性是可以修改的。因为const实质上保证的并不是变量的值不得改动,而是变量指向的内存地址的值不得改动。
补充:ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”。
二、call、apply、bind的区别
补充: 怎么改变this的指向:
1、使用 ES6 的箭头函数
2、在函数内部使用 _this = this
3、使用 apply、call、bind
4、new 实例化一个对象
三、深拷贝和浅拷贝的区别
四、箭头函数和普通函数的区别
1、外形不同:箭头函数使用箭头定义,普通函数中没有
2、箭头函数全都是匿名函数:普通函数可以有匿名函数,也可以有具名函数
3、箭头函数不能用于构造函数:普通函数可以用于构造函数,以此创建对象实例
4、箭头函数中this的指向不同:
箭头函数本身没有this,但是在它声明的时候,能够捕获此函数所在作用域中this。
特别说明:this一旦被捕获,以后将不再变化。call、apply、bind可以改变普通函数的this指向,但不能改变箭头函数的在普通函数中,this总是指向调用它的对象或者,如果用作构造函数,它指向创建的对象实例。
5、箭头函数不具有arguments对象:
每一个普通函数调用后都具有一个arguments对象,用来存储实际传递的参数。
但是箭头函数并没有此对象。
五、web storage和cookie的区别
相同点:都存储在客户端
不同点:
1、存储大小:cookie数据大小不能超过4k;sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
2、有效时间:
名称|有效时间
–|:–😐–:
localStorage|存储持久数据,浏览器关闭后数据不丢失除非主动删除数据
sessionStorage|数据在当前浏览器窗口关闭后自动删除
cookie|设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
3、数据与服务器之间的交互方式:
cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端,
每次你请求一个新的页面的时候Cookie都会被发送过去,这样无形中浪费了带宽。cookie还需要指定作用域,不可以跨域调用。sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
六、Js基本数据类型
5中简单数据类型: undefined、null、number、boolean、string、symbol、bigint
1种复杂的数据类型: Object
es6新增数据类型Symbol:symbol 是唯一的,它和任何其他symbol 都不相等,避免了属性名的冲突。
七、常见的HTTP状态码
1、200 正常处理并返回
2、301 永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL
3、302 临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新的URL
4、400 请求报文中语法错误
5、401 没有权限
6、403 服务器拒绝此次访问、禁止访问。尝试访问(被禁止的)网站目录时,就会发生403错误
7、404 找不到网页
8、500 服务器内部错误,无法完成此次请求
9、502 无效网关
10、503 服务器超载或停机 目前无法使用
八、display:none、visibility:hidden区别
1、1.display:none是彻底消失,不在文档流中占位,浏览器也不会解析该元素;visibility:hidden是视觉上消失了,可以理解为透明度为0的效果,在文档流中占位,浏览器会解析该元素。
2、使用visibility:hidden比display:none性能上要好,display:none切换显示时visibility,页面产生回流(当页面中的一部分元素需要改变规模尺寸、布局、显示隐藏等,页面重新构建,此时就是回流。所有页面第一次加载时需要产生一次回流),而visibility切换是否显示时则不会引起回流。
九、什么叫优雅降级和渐进增强
1、渐进增强:针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。
2、优雅降级:一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。
区别:
a. 优雅降级是从复杂的现状开始,并试图减少用户体验的供给
b. 渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要
c. 降级(功能衰减)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带
十、css水平、垂直居中的写法
水平居中:
1、行内元素: text-align: center
2、块级元素: margin: 0 auto
3、position: absolute + left: 50% + transform: translateX(-50%)
4、dispaly: flex + justify-content: center
垂直居中:
1、设置line-height
等于height
2、position: absolute + top: 50% + transform: translateY(-50%)
3、dispaly: flex + algin-items: center
4、父元素dispaly: table + 子元素dispaly: table-cell + vertical-align: middle
(默认情况下,图片,按钮,文字和单元格都可以用vertical-align属性)
十一、函数防抖与节流使用场景
防抖:
1、搜索框搜索输入。只需用户最后一次输入完,再发送请求。
2、手机号、邮箱验证输入检测。
3、窗口大小Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
节流:
1、滚动加载,加载更多或滚到底部监听。
2、谷歌搜索框,搜索联想功能。
3、高频点击提交,表单重复提交。
参考1
参考2
十二、js如何一次性展示十万条数据
1、一次性渲染(很卡顿,渲染时间很长)
2、利用setTimeout
分组数据异步执行,分批加载
3、利用window.requestAnimationFrame
分批加载
4、window.requestAnimationFrame
+documentFragment
eg:(假设在ul
列表里插入十万个li
)
const total = 100000 // 数据总数
let oContainer = document.getElementById('container') // 要插入数据的容器
const once = 2000 // 一次性插入的条数
const page = total / once // 总的页数
const index = 0 // 数据的索引
const insert = (curTotal, curIndex) => {
if (curTotal <= 0) {
return
}
window.requestAnimationFrame(() => {
let fragment = document.createDocumentFragment()
for (let i = 0; i < once; i++) {
let oLi = document.createElement('li')
oLi.innerHTML = curIndex + i
fragment.appendChild(oLi)
}
oContainer.appendChild(fragment)
insert(curTotal - once, curIndex + once)
})
}
insert(total, index)
十三、跨域
所谓同源是指"协议+域名+端口"三者相同,只要有其一不同则为跨域
解决跨域:
简单的跨域请求jsonp即可,复杂的cors,窗口之间JS跨域postMessage,开发环境下接口跨域用nginx反向代理或node中间件比较方便。
1、设置document.domain解决无法读取非同源网页的 Cookie问题
2、跨文档通信 API:window.postMessage() (只支持GET请求)
3、Jsonp(只支持GET请求)
4、CORS
5、WebSocket协议跨域
6、nginx反向代理
7、hash + iframe (只支持GET请求)
十四、闭包
闭包即函数和函数所有变量的总和。
闭包指的是能够访问另一个函数作用域的变量的函数。
闭包就是一个函数,这个函数能够访问其他函数的作用域中的变量
闭包用途
1、读取函数内部的变量
2、让这些变量的值始终保持在内存中。不会再f1调用后被自动清除。
3、方便调用上下文的局部变量。利于代码封装。(封装私有变量)
4、函数防抖
十五、从URL输入到页面展现发生了什么
这是一篇讲得特别全面得文章:
参考
十六、性能优化方案
1、初始化页面加loding图(提升用户体验)
2、 减少http请求和冗余数据
3、组件,路由懒加载
4、配置nginx优化
5、优化wepack打包机制
6、使用CDN
7、预渲染
8、SSR
9、图片转base64
10、后台分布式部署,负载均衡
十七、SSR
SSR: 即服务端渲染。将组件或页面通过服务器生成html字符串,再发送到浏览器,最后将静态标记"混合"为客户端上完全交互的应用程序。
优点:
1、更利于SEO
2、更利于首屏渲染
缺点:
1、服务端压力较大
2、开发条件受限
3、学习成本相对较高
客户端渲染:
优点:
1、减少服务器压力
2、可以实现局部刷新,无需每次都请求完整的页面,体验更好
缺点:
1、前端耗时较多,首屏渲染慢,渲染前要下载一堆js和css文件
2、不利于SEO,爬虫看不到完整的代码
十八、微任务宏任务
宏任务:包括整体代码script,setTimeout,setInterval,setImmediate,xhr,callback
微任务:Promise.then,process.nextTick
有以下试题:最终结果为 2-4-3-1
setTimeout(function () {
console.log('1')
})
new Promise(function (resolve) {
console.log('2')
resolve()
}).then(function () {
console.log('3')
})
console.log('4')
十九、script标签中defer和async的区别
- defer:浏览器指示脚本在⽂档被解析后执⾏,script被异步加载后并不会⽴刻执⾏,⽽是等待⽂档被解析完毕后执⾏。如果有多个设置了defer的script标签存在,则会按照顺序执行所有的script。
- async:同样是异步加载脚本,区别是脚本加载完毕后⽴即执⾏,这导致async属性下的脚本是乱序的,对于script 有先后依赖关系的情况,并不适⽤。并不会按着script在页面中的顺序来执行,而是谁先加载完谁执行。
蓝⾊线代表⽹络读取即加载时间,红⾊线代表执⾏时间,这俩都是针对脚本的;绿⾊线代表 HTML 解析
二十、如何判断是否是数组
if(!Array.isArray){
Array.isArray = function(arg){
return Object.prototype.toString.call(arg)==='[object Array]'
}
}
二十一、null与undefined的区别是什么?
-
null是“不代表任何值的值”。null是已明确定义给变量的值。在此示例中,当fs.readFile方法未引发错误时,我们将获得null值。⼀个对象可以是null,代表是个空对象,⽽null本身也是对象。
-
undefined是未指定特定值的变量的默认值,或者没有显式返回值的函数,如:console.log(1),还包括对象中不存在的属性,这些 JS 引擎都会为其分配 undefined 值。undefined表示『不存在』,JavaScript是⼀⻔动态类型语⾔,成员除了表示存在的空值外,还有可能根本就不存在(因为存不存在只在运⾏期才知道),这就是undefined的意义所在。
-
null是一个表示"无"的对象,转为数值时为0;
Number(null) // 0
- undefined是一个表示"无"的原始值,转为数值时为NaN。
Number(undefined) // NaN
null == undefined //true
null === undefined // false
二十二、为什么此代码 obj.someprop.x
会引发错误?
const obj = {};
console.log(obj.someprop.x);
显然,由于我们尝试访问someprop属性中的x属性,而 someprop 并没有在对象中,所以值为 undefined。记住对象本身不存在的属性,并且其原型的默认值为undefined。因为undefined没有属性x,所以试图访问将会报错。
二十三、数组去重
二十四、一些转换字符串
根据MDN文档,+
是将字符串转换为数字的最快方法,因为如果值已经是数字,它不会执行任何操作。
+'2' // 2
!!
运算符可以将右侧的值强制转换为布尔值,这也是将值转换为布尔值的一种简单方法。
console.log(!!null); // false
console.log(!!undefined); // false
console.log(!!''); // false
console.log(!!0); // false
console.log(!!NaN); // false
console.log(!!' '); // true
console.log(!!{}); // true
console.log(!![]); // true
console.log(!!1); // true
console.log(!![].length); // false
参考文档
未完待续…