Symbol和BIgInt都是做什么的?
1、Symbol()返回的symbol值都是唯一的。一个symbol值能作为对象属性的标识符;这是该数据类型仅有的目的。
let var_symbol = Symbol();
let other_symbol = Symbol();
console.log(var_symbol === other_symbol);
// false
console.log(typeof var_symbol);
// symbol
console.log(var_symbol.constructor === Symbol)
// true
2、
--BIgInt 是一种数字类型的数据,它可以表示任意精度格式的整数。BigInt 只用来表示整数,没有位数的限制,任何位数的整数都可以精确表示
--为了与 Number 类型进行区分,BigInt 类型的数据必须添加后缀n。
--由于 BigInt 与 Number 完全属于两种类型,并且不会进行隐式转换,所以没有办法进行混合运算。想要运算的话,必须将两种数据类型转换为同一类型后,方可进行计算:
BigInt(number) // 将一个 Number 转换为 BigInt
Number(bigint) // 将一个 BigInt 转换为 Number
Symbol如何创建两个相等的值?
用 Symbol.for() 方法创建的的 symbol 会被放入一个全局 symbol 注册表中。Symbol.for() 并不是每次都会创建一个新的 symbol,它会首先检查给定的 key 是否已经在注册表中了。假如是,则会直接返回上次存储的那个。否则,它会再新建一个
let var_symbol = Symbol.for('symbol');
let other_symbol = Symbol.for('symbol');
console.log(var_symbol === other_symbol)
// true
parseInt和Number的区别?
两个都是将内容转换成数字类型的函数
parseint:
如果以数字开头,就会返回开头的合法数字部分,如果以非数字开头,则返回NaN,
如果是小数,返回整数部分
Number:
如果不是数字,或者数字字符串, 会返回NaN(Not a Number);
如果是小数,返回整体
Number('100') 100
parseInt('100') 100
Number('19.92'). 19.92
parseInt('19.92') 19
parseInt('100dd') 100
Number('100dd') NAN
parseInt('ddd')NAN
Number('ddd') NAN
什么叫做执行栈,什么叫做执行上下文?
执行栈:
倡导先进后出的特点,当进入一个执行环境,就会创建它的执行上下文,然后进行
压栈,当程序执行完成,执行上下文就会被销毁,然后进行弹栈。
执行上下文:
· 全局执行上下文:
创建一个全局window对象,将this执行window,执行js的时候压入栈底,关闭浏览器的时候弹出。
· 函数执行上下文:
每次函数执行的时候,就会新创建一个函数执行上下文;
分为两个阶段 创建阶段和执行阶段
创建阶段: 创建arguments对象声明并赋值, 创建函数声明并赋值,创建变量声明不赋值,函数表达式声明不赋值, 确定this指向,确定作用域;
执行阶段:变量赋值,函数表达式赋值
· eval执行上下文
typeof和instanceof的区别? instanceof的原理?
1、typeof可以判断数据类型 值类型(boolean,string,number, symbol,null, undefined, function),能识别引用类型,但是不能判断具体引用类型( object, array)
2、instanceof用来检测某个对象是不是另一个对象的实例,即在其原型链中是否存在一个构造函数prototype属性
instanceof的原理,就是查找目标对象的原型链,即查找实例对象的隐式原形是否指向它的构造函数的显示原形
为什么typeof null是object?
000:对象 null的二级制前
010:浮点数
100:字符串
110:布尔
1:整数
字面量创建对象和new创建的对象有什么区别?new内部做了什么?手写new函数
字面量创建更简单,更容易阅读
不需要作用域解析
new做了什么:
1、创建了一个对象
2、使新对象的__proto__指向原函数的prototype
3、将this指向新的对象并执行该函数,执行结果保存result
4、判断执行结果是null或是undefined,如果是返回原的对象,不是返回result
function myNew(fn, ...args) {
let obj = {}
obj.__proto__ = fn.prototype
let result = fn.apply(obj, args)
return result instanceof Object ? result : obj
}
new创建的对象和Object.create(null)创建出来的对象有什么区别?
字面量和new继承object的原形和方法,但是Object.create(null)创建的对象是原型链的顶端,自然没有继承object的属性和方法。
js的继承方式有哪些以及各种方式的优缺点?
1、类继承
2、原型链继承
3、组合继承
4、构造函数继承
垃圾回收机制都有哪些策略?
1、标记清除
当一个变量进入执行环境,就会被标记来自他的引用,在程序运行中,如果发现没有被标记引用的变量,就会被清除,已经进入执行环境的不能被清除
2、引用计数
当声明一个变量并给这个变量赋值一个引用类型的时候,就会计数+1,当该值被其他值取代时-1, 当计数为0时,就可以做回收。但是当两个对象互相引用的时候,就会出问题。
es6和commonjs的区别?
1、commonjs引入的值的拷贝,es6是值的引用
2、commonjs是运行时编译,es6是编译时加载
3、commonjs的this指向当前模块,es6this指向undefined
js的事件流阶段?
1,事件捕获阶段。
2,处于目标阶段。
3,事件冒泡阶段。
instanceof 和constructor的区别?
1,instacnceof是运算符,主要用来判断一个对象是否是他的构造函数的实例
constructor是object的一个属性,在继承中使用super,其实指向的就是父级的constructor
2、instanceof可以判断多层继承,不仅可以判断是直接类的实例,还可以判断父级的实例,
constructor只可以判断直接类的实例
a instanceof A 为true
a instanceof Object 也为true
a.constructor == A 为true
a.constructor == object 为false
深拷贝的方式有哪些? 手写深拷贝?
1、递归去赋值去所有层级
2、JSON.parse和JSON.Stringify
3、 lodash工具库
浅拷贝, 浅拷贝的方法?
只针对对象的第一层数据,基本类型的数据是值的copy,但是引用类型依然是copy了引用地址,相互之间会产生影响。
**浅拷贝的方法:
Object.assign({}, obj)
es6的解构复制
数组的slice(), contact()
class和function的区别?
相同点: 都可以使用构造函数
不同点: class不可以使用call,bind, apply改变this的执行上下文
js的严格模式有什么特点?
禁止this指向window
with语法 eval语法
全局变量先声明再使用
函数参数不能重名
判断数据类型的方式有哪些?
1、 typeof
2、instanceof
3、通过Object下的toString.call()方法来判断
console.log(toString.call(123)); //[object Number]
console.log(toString.call('123')); //[object String]
console.log(toString.call(undefined)); //[object Undefined]
console.log(toString.call(true)); //[object Boolean]
console.log(toString.call({})); //[object Object]
console.log(toString.call([])); //[object Array]
console.log(toString.call(function(){})); //[object Function]
4、根据对象的contructor判断
console.log(arr.constructor === Array); //true
console.log(date.constructor === Date); //true
console.log(fn.constructor === Function); //true
mvc和mvvm的区别?
MVC是单向通信,通过Controller来承上启下, model和view不单独联系
MVVM是双向通信,model和view的变化,都能够通过viewmodel监听到,通过执行响应的方法
MVVM解决了MVC中大量的dom操作使页面渲染性能降低,加载速度变慢,影响用户体验
mvc模式?
mvc模式是一种架构,也是一种思想,通过视图(看的见得),模型(业务逻辑,算法,输出对象等),控制器(接受用户的输入,去调用模型和视图,去完成用户的请求),达到轻松分离业务,UI,逻辑控制的功能
mvc的缺点?
1、model直接对外暴漏了操作方式,就导致视图层,可以随意更改model中的数据,也可以随意监听model中的数据变化
函数声明与函数表达式的区别?
newObject Object.create的区别?
js的this问题?
上边1 下边 undefined
RAF?
性能优化从哪几个方面?
箭头函数和普通函数的区别?
Promise的了解?![](https://img-blog.csdnimg.cn/f4f134562b494d52ab40d9e1cfaeb11b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56iL5bqP5ZGY54On54Ok5bqX,size_20,color_FFFFFF,t_70,g_se,x_16)
浏览器事件循环与node事件的区别?
for和forEach哪个更快?
什么是jsbridge?
如何实现SSO单点登录?
URL参数解析为js对象
手写trim?
获取最大值?![](https://img-blog.csdnimg.cn/1db6fb26bc0d48e294c788ad8c0dd9d6.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56iL5bqP5ZGY54On54Ok5bqX,size_20,color_FFFFFF,t_70,g_se,x_16)
script中的defer和async有什么区别?
HTTP协议和UDP协议的区别?
HTTP1.0和HTTP1.1的区别?
了解HTTP缓存吗?
什么是回流和重绘?
什么情况下出发BFC?
如何实现网页多标签tab通信?
后端一次性返回给你10W条数据?
提升页面的性能有哪些?
同步和异步的区别是什么?
promise的原理?你是如何理解promise的?
把异步处理规范化, promise的核心原理其实就是发布订阅模式,通过两个队列来缓存成功的回调(onResolve)和失败的回调(onReject)
使用promise请求一张图片,包括成功和失败状态?
function loadImg(src) {
return new Promise((resolve, reject) => {
const img = document.createElement('img')
img.onload = () => {
resolve(img)
}
img.onerror = () => {
const err = new Error(`图片加载错误${src}`)
reject(err)
}
img.src = src
})
}
const url1 = 'https://img.mukewang.com/5a9fc8070001a82402060220-140-140.jpg'
loadImg(url1).then(img1 => {
console.log(img1.width)
})
宏任务和微任务有哪些? 为什么微任务比宏任务执行的要早?
// 去除对象数组中指定的元素
const arr = [{ name: 'jack', age: 19 }, { name: 'rose', age: 20 }]
function cutArray(sourceArray, target) {
sourceArray.forEach((item, index) => {
if (item.name === target) {
sourceArray.splice(index, 1)
}
})
return sourceArray
}
console.log(cutArray(arr, 'jack')) // rose
变量和函数怎么进行提升的?优先级怎么样?
>>>>>函数优先级大于变量优先级, 但是如果变量被重新赋值,就会覆盖函数
console.log(a) // fa()
var a=1;
function a(){}
console.log(a) // 1
函数声明和函数表达式的区别?
new Object和Object.create()的区别?
const obj1 = {
a: 10,
b: 20,
sum() {
return this.a + this.b
}
}
const obj2 = new Object({
a: 10,
b: 20,
sum() {
return this.a + this.b
}
})
const obj21 = new Object(obj1) // obj1 === obj2
const obj3 = Object.create(null) // 没有原型
const obj4 = new Object() // {}// 有原型
const obj5 = Object.create({
a: 10,
b: 20,
sum() {
return this.a + this.b
}
})
const obj6 = Object.create(obj1)
说说你对代理的理解?
中介
>>>>>>有暂存代理, 就是说请求了一次,将数据缓存起来,下次再请求发现参数一直,就可以直接使用缓存的数据
>>>>>>虚拟代理, 就是在暂时不需要的时候,先不请求,有点类似按需加载
>>>>>>应用场景
现在的很多前端框架或者状态管理框架都使用代理模式,用于监听变量的变化
使用代理模式代理对象的访问的方式,一般又被称为拦截器,比如我们在项目中经常使用 Axios 的实例来进行 HTTP 的请求,使用拦截器 interceptor 可以提前对 请求前的数据 服务器返回的数据进行一些预处理
为什么要使用模块化?
>>>>>>可以抽离公共组件,减少代码体积,提供更多的可复用性
exports和module.exports有什么区别? export和export default有什么区别?
>>>>>exports和module.exports没任何区别
1.module.exports 和exports 是commonjs的规范
2.export 和export default 是es6 规范
3.require 是amd规范引入方式
4.import 是es6 的一个语法标准
导入的区别
闭包的理解、闭包的作用、闭包所带来的的问题?
100 100 所变量的执行都是在自己定义的作用域中去查找
js的作用域和作用域链?
>>>>>js的作用域就是函数的可执行范围
>>>>>作用域链就是,函数想寻找一个变量,会优先在自己的内部查找,自己内部找不到就会往自己的上层查找,一直找到windon,找不到就报错
js的原形和原型链?
什么是防抖和节流?
>>>>>代码实现?
// 防抖
var int = document.getElementById('int')
var t;
int.addEventListener('keyup', (e) => {
if (t) {
clearTimeout(t)
}
t = setTimeout(() => {
console.log(e.target.value)
}, 1500)
})
// 节流
var int = document.getElementById('int')
var t;
int.addEventListener('keyup', (e) => {
if (t) {
return
}
t = setTimeout(() => {
console.log(e.target.value)
t = null
}, 1500)
})
forEach和map的区别?
>>>>>forEach没有返回值,不会产生新的数组
>>>>>map有返回值,产生新的数组
相同点:
都支持三个参数,参数分别为item(当前每一项),index(索引值),arr(原数组)
使用setTimeout实现setInterval?
function mySelfInterval(){
console.log(1)
let t = setTimeout(() => {
mySelfInterval()
clearTimeout(t)
}, 2000)
}
mySelfInterval()
创建10个a标签,点击弹出对应的序号?
for (let i = 0; i< 10; i++) {
var targetA = document.createElement('a')
targetA.innerHTML = '序号' + (i + 1)
targetA.addEventListener('click', function () {
console.log(i)
})
document.body.append(targetA)
}
值类型和引用类型?
存贮,拷贝,赋值机制,根据内存和CPU之间的耗时 来做的区分
this指向? 同步和异步的区别是什么?
手写bind函数?
DOM属于哪种数据结构,有哪些常用的API , attr和property的区别?
树形结构
一次性插入多个dom节点,考虑性能?
文档片段, 减少dom操作?
频繁操作改为一次性操作
const list = document.getElementById('list')
// 创建一个文档片段,此时还没有插入到 DOM 结构中
const frag = document.createDocumentFragment()
for (let i = 0; i < 20; i++) {
const li = document.createElement('li')
li.innerHTML = `List item ${i}`
// 先插入文档片段中
frag.appendChild(li)
}
// 都完成之后,再统一插入到 DOM 结构中
list.appendChild(frag)
console.log(list)
常见的DOM操作?
const div1 = document.getElementById('div1')
const div2 = document.getElementById('div2')
// 新建节点
const newP = document.createElement('p')
newP.innerHTML = 'this is newP'
// 插入节点
div1.appendChild(newP)
// 移动节点
const p1 = document.getElementById('p1')
div2.appendChild(p1)
// 获取父元素
console.log( p1.parentNode )
// 获取子元素列表
const div1ChildNodes = div1.childNodes
console.log( div1.childNodes )
const div1ChildNodesP = Array.prototype.slice.call(div1.childNodes).filter(child => {
if (child.nodeType === 1) {
return true
}
return false
})
console.log('div1ChildNodesP', div1ChildNodesP)
div1.removeChild( div1ChildNodesP[0] )
webpack如何将es6变成es5?
window.onload和DOMConentLoaded? ![](https://img-blog.csdnimg.cn/ff84564be21a495ba26e909fe1cd035a.png)
前端性能优化?
前端常见的web攻击方式有哪些?
var let const 区别?
数组的常见操作?
splice 剪接的意思 非纯函数
第一个参数是开始位置, 第二个参数是截取接个,,后边的参数会部位到开始位置的后边
var abc = [1, 2, 3, 4, 5]
abc.splice(0, 1) // 会改变原数组,返回删除的元素
console.log(abc)
// [2, 3, 4, 5]
slice 切片的意思
纯函数 第一个参数是开始的位置,第二个参数是结束的位置
没有第二个参数默认到结尾
var abc = [1, 2, 3, 4, 5]
abc.slice(0, 1) // slice() 返回一个新的数组,不改变原数组
// [1]
filter 不改变原数组,产生新的数组
var abc = [1, 2, 3, 4, 5]
abc.filter(item => item > 3)
console.log(abc)
// [1, 2, 3, 4, 5]
map 不改变原数组, 产生新的数组
var abc = [1, 2, 3, 4, 5]
var abc2 = abc.map(item => {
return item > 3
})
console.log(abc2)
//[false, false, false, true, true]
every, 如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
如果所有元素都满足条件,则返回 true。
every, 不会改变原始数组
var abc = [1, 2, 3, 4, 5]
abc.every(item => item < 3)
// false
var abc = [1, 2, 3, 4, 5]
abc.every(item => item > 0)
// true
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
var abc = [1, 2, 3, 4, 5]
abc.reduce((item, index) => item + index) // 15
some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。 备注:与every方法效果一样!!
some() 方法会依次执行数组的每个元素:
如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。
如果没有满足条件的元素,则返回false。
pop尾部删除,返回删除的元素,改变原数组
shift前边删除,返回删除的元素,改变原数组
unshift方法和push方法分别为头部和尾部添加元素
数组降维
let arrAy = [ [1, 2, 2,3], [2, 3, 4, 5], [6, 6,7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]
let ret = []
function fallten(arr) {
arr.forEach(item => {
Array.isArray(item) ? fallten(item) : ret.push(item)
})
}
fallten(arrAy)
console.log(ret)
去重
let arrAy = [ [1, 2, 2,3], [2, 3, 4, 5], [6, 6,7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]
let ret = []
function fallten(arr) {
arr.forEach(item => {
Array.isArray(item) ? fallten(item) : ret.push(item)
})
}
fallten(arrAy)
console.log(ret)
let setRet = []
ret.forEach(item => {
if (setRet.indexOf(item) < 0) {
setRet.push(item)
}
})
console.log(setRet)
// 配合冒泡排序
let arrAy = [ [1, 2, 2,3], [2, 3, 4, 5], [6, 6,7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]
let ret = []
function fallten(arr) {
arr.forEach(item => {
Array.isArray(item) ? fallten(item) : ret.push(item)
})
}
fallten(arrAy)
console.log(ret)
let setRet = []
ret.forEach(item => {
if (setRet.indexOf(item) < 0) {
setRet.push(item)
}
})
console.log(setRet)
console.time()
for(var i = 0; i< setRet.length - 1; i++) {
for (var j = 0; j < setRet.length - 1 - i; j++) {
if (setRet[j]> setRet[j+1]) {
var temp = setRet[j]
setRet[j] = setRet[j + 1]
setRet[j + 1] = temp
}
}
}
console.log(setRet)
console.timeEnd()
快速排序
console.time()
function quickSort(tempArr) {
if (tempArr.length <= 1) {
return tempArr
}
var leftIndex = Math.floor(tempArr.length / 2)
var checkItem = tempArr.splice(leftIndex, 1)
var left = []
var right = []
for(var i = 0; i< tempArr.length; i++) {
if (tempArr[i] < checkItem) {
left.push(tempArr[i])
} else {
right.push(tempArr[i])
}
}
return quickSort(left).concat(checkItem, quickSort(right))
}
console.log(quickSort(setRet))
console.timeEnd()
手写深度比较 ?
for in for of的区别 ?
for in遍历的是数组的索引(即键名),而for of遍历的是数组元素值
for in总是得到对象的key或数组、字符串的下标
for of总是得到对象的value或数组、字符串的值
call和apply的区别 ?
console.log([10, 20, 30].map(parseInt))
console.log([10,20,30].map((item, index) => {
return parseInt(item, index)
}))
parseInt的第二个参数是要解析的数字的基础,在2---36之间,如果该参数小于2或者大于36,则parseInt()返回NAN
如何捕获js中的异常 ?
js闭包是内存泄漏吗?
不是内存泄漏, 闭包是合理预期的, 因为闭包的使用,就是不想让外部去污染函数内部的变量,
闭包内部的变量只是不能够及时被回收。
如何检测JS内存泄漏?
如果内存持续在升高,google浏览器的performance中选择memory可以检测内存使用的变化。
js内存泄漏的场景有哪些?
虚拟dom真的快吗?
并不是快,js直接操作DOM更快,而是去服务于数据驱动视图的开发思想,更合适。
nodejs如何开启多进程,进程如何通讯?
nodejs 进程如何使用child_process.fork?
nodejs 进程如何使用cluster?
requestdlecallback和requestAnimationFrame的区别?
vue的每个生命周期都做了什么?
vue什么时候操作DOM更合适?
三次握手和四次挥手?
session和JTW哪个更好?
如何实现SSO单点登录?
HTTP1.0, 2.0 的区别?
什么事HTTPS中间人攻击,如何预防?
中间人攻击,就是在客户端与服务端交互中,通过设置自己的公钥私钥来截取信息,
要通过正规的证书预防
对称加密:
需要同样的密码加密解密,因为密码存在服务端,需要客户端获取密码,容易被截取密码
非对称加密:
公钥加密,私钥解密
websocket与HTTP有什么区别?
websocket支持端对端通信,可以有client发起,也可以由server发起
用途: 消息通知,聊天室,直播, 协同编辑
从输入URL到网页展示的完整过程?
***如何实现网页多个tab通讯?
***如何实现网页和ifame通讯?
postMessage
H5页面如何进行首屏优化?
1、路由懒加载,优先保证首页加载
2、服务端渲染,如果是纯H5, SSR是终极解决方案
3、APP预取配合hybrid,将打包的文件,放在APP运行的沙盒环境中,通过file协议来交互
4、分页
5、图片懒加载,但是要提前定义好图片尺寸,避免重拍