JS面试题

时间:2021-6-12 作者:qvyue

数据类型

Number
String
boolean
Symbol
undefined
null
BigInt
Object
Array

六种假值

false
‘ ‘
0
undefined
null
NAN

es6新特性

解构赋值 {}
展开运算符 …
对象属性的简写
let const
箭头函数 ()=>{} 箭头函数是函数表达式的语法糖 在哪定义this指向谁
Symbol 生成一个唯一值
Object.assign 一层深拷贝
Set 集合数据类型 用来存放数组但是数组元素不能重复
Map 类似于对象 可以使用任何数据类型来作为属性名 可以是中文
class 定义类
for of 语句
promise async await 对象 解决回调地狱
module ES6模块化

Math

Math对象是JavaScript的内置对象,提供一系列数学常数和数学方法。Math对象只提供了静态的属性和方法,所以使用时不用实例化。
Math.round(0.1)//0 四舍五入
Math.abs(-1)//1 取绝对值
Math.max(2, -1, 5) // 5 max方法返回最大的参数
Math.min(2, -1, 5) // -1 min方法返回最小的参数。
Math.floor(3.2) // 3 向下取整
Math.ceil(3.2) // 4 向上取整
Math.pow(2, 3) // 8 pow方法返回以第一个参数为底数、第二个参数为幂的指数值。
Math.sqrt(-4) // NaN sqrt方法返回参数值的平方根。如果参数是一个负值,则返回NaN。
Math.random() 该方法返回0到1之间的一个伪随机数,可能等于0,但是一定小于1。
返回给定范围的随机数。

function getRandomArbitrary(min, max) {
  return Math.random() * (max - min) + min;
}

Set

Set 与数组类似, Set 集合中的元素不重复。
size 获取当前Set对象的长度
add(value) 向当前Set对象中添加一个值,返回的是Set对象,所以支持链式写法
delete(value) 删除当前Set对象中的一个值,返回一个布尔值,表示是否删除成功
has(value) 检测这个value是否是当前Set对象的一个元素,通过返回的布尔值表示
clear() 清除当前Set对象所有元素,没有返回值

Map

ES6新增了Map数据结构,Map对象保存键值对,任何值(原始值或对象)都可以作为一个键或一个值。

Map是一组键值对,有key 也有value。

初始化Map需要一个二维数组,或者直接初始化一个空Map。 Map具有以下方法:

set ,添加key-value

has,判断是否存在key

get,获取对应key的值

delete, 删除对应的key以及value

es6模块化

1.默认模块只能导出一个 export default
2.非默认模块可以导出多个 export
3.引入非默认模块需要同名并加{}
4.默认模块和非默认模块可以同时引入 如: import a,{b} from “../index”

事件冒泡的三个阶段

事件捕获
触发事件的事件源
事件冒泡

异步同步

异步是耗时的 当浏览器解析到异步代码时会将异步代码挂起先执行同步代码,等待同步代码全部执行完,浏览器空闲的时候才会执行异步代码
ajax 定时器

事件循环

主线程=>微任务=>宏任务
promise是微任务
计时器是宏任务

事件监听

绑定监听事件 可以绑定相同事件
addEventListener
removeEventListener
注意 如果需要解绑 必须写函数名
优点: 同一个元素可以绑定多个相同事件的处理程序
根据需求可以把指定的已经邦过的处理程序解绑
符合W3C标准(都兼容)

事件委托

当有多个同级dom需要绑定相同事件时,可以使用事件委托来处理,事件委托不管有多少个子元素 只开辟一个函数空间,而一个一个绑定事件,会生成相同多的函数空间
事件委托的优点:
1.节约内存,性能优化
2.动态添加的dom也有可以触发该事件

访问标签属性

getAttribute
setAttribute

js dom操作

1.创建dom
document.createElemen(标签名) 创建一个元素节点
2.添加dom
parent.appendchild(child);向parent(父元素)中添加 child(节点),添加到最后边
3.移除节点
parent.removeChild(child) 移除parent里的child
4.替换节点
parent.replaceChild(新节点,旧节点)//用新节点替换 parent父元素里的旧节点
5.克隆节点
dom.cloneNode(布尔值) true为深拷贝 false为浅拷贝

访问元素的类名(classList是H5新增的API)

1.添加类名 dom.classList.add(类名)
2.删除类名 dom.classList.remove(类名)
3.替换类名 dom.classList.replace(旧类名,新类名)
4.是否包含某个类名 dom.classList.contains(类名)—–>返回布尔值

js 鼠标移入移出事件的区别

mouseover 和 mouseout 当从父元素移到子元素(从子元素移到父元素)上时会先触发移出再触发移入
mouseenter 和 mouseleave 不会因为从父元素移到子元素从子元素移到父元素)触发

自定义属性的三种方式

1.setAttribute
2.data-i
3.通过对象的.方式直接给标签添加属性 dom.i=XXX

ajax的作用 ajax的工作原理

ajax异步请求 局部更新
工作原理:
1.创建xhr对象
2.用open方法配置请求方式和url
3.用send方法发送请求
4.监听xhr的状态变化 xhr.readyState
5.把数据渲染到页面上

深拷贝

1.一层深拷贝 Object.assign
2.粗暴深拷贝 JSON.parse( JSON.stringify())
3.完美深拷贝 使用递归去拷贝所有层级属性

      let oldObj = {
        name: "张三",
        colors: ["blue", "red", "white"],
      };
      let newObj;
      function copy(obj = {}) {
        if (typeof obj !== "object" || obj === null) {
          return obj;
        }
        let result;
        if (obj instanceof Array) {
          result = [];
        } else {
          result = {};
        }
        for (let key in obj) {
          if (obj.hasOwnProperty(key)) {
            result[key] = copy(obj[key]);
          }
        }
        return result;
      }
      newObj = copy(oldObj);
      newObj.name = "李四";
      newObj.colors[0] = "black";
      console.log(newObj, "newObj");
      console.log(oldObj, "oldObj");

数组方法

es5:
arr.indexOf 查询某个值在数组中的索引 如果不存在返回-1
arr.push 向数组末尾添加元素
arr.join 把数组中所有元素转化为一个字符串
forEach 不需要明确循环次数,直接获取值 不能用black 跳过
map 实现遍历 要有返回值 返回值会构成新的数组
filter 实现遍历 要有返回值 会获取所有返回值为真的数据 并构成新的数组
every 实现遍历 要有返回值 如果全部数据都返回真则结果为真
some 实现遍历 要有返回值 如果有一个为真,结果就为真
es6:
arr.reduce 累加数组

数组去重

1.利用filter+indexOf
2.利用对象属性去重
定义一个空对象
用for循环遍历数组中所有元素
如果在对象中没有这个属性则添加进新数组
3.利用indexOf查询
4.es6的Set方法
let res = new Set()
arr.forEach(x=>res.add(x))

选出数组里的最大值和最小值

使用apply
Math.max.apply(null,arr) null代表占位符
Math.min.apply(null,arr) null代表占位符

合并数组合并对象

1.合并数组
arr1.concat(arr2)
2.合并对象
Object.assign(obj1,obj2,obj3)

判断一个变量是不是数组

1.instanceof. arr instanceof Array
2.constructor [].constructor
3.Array.isArray([])
4.Array.prototype.isPrototypeOf([]) 用于指示对象是否存在于一个原型链中 如果存在返回true

call apply 和bind的区别

call和apply 都是执行函数改变this指向
bind 是改变函数的this指向 返回改变后函数的地址

普通函数与构造函数的区别

构造函数使用new创建 普通函数不需要new
普通函数的this指向他的调用者
构造函数的this指向他的实例

原型链

1.原型对象:所有函数在初始化的时候都会自动生成一个特殊的实例化对象,函数的prototype属性指向该对象,该对象即为原型对象
2.proto属性:所有new出来的实例化对象自身都有一个proto属性,该属性指向构造函数的原型对象
3.原型链:实例的proto属性指向构造函数的原型对象,而原型对象也有自己的proto属性,指向上一级的构造函数的原型对象,依次查找最后会指向Object的原型对象,Object原型对象的proto指向null,由一系列proto所串联的原型对象构成原型链
4.原型链的意义:实现继承 当构造函数的实例调用属性和方法时 会先从自身找 如果自身没有就会沿着原型链一层一层向上找

闭包

函数内部通过return把子函数暴露在全局,可以在全局调用这个子函数,所以当父函数执行完毕时不会被销毁
当在全局调用该子函数时 子函数的作用域还是在 父函数中 所以调用变量还是会从自身=>父函数=>全局 沿着作用域链依次查找
好处是减少了全局变量的命名冲突
坏处是使用不当会造成内存泄漏 该销毁的没有销毁一直存在在内存中

new一个实例化对象经历的四个阶段

创建一个空实例化对象
改变构造函数的this指向 指向该实例
执行构造函数,使空实例化对象生成自己的属性和方法
把实例化对象的地址赋值

继承

1.原型链继承
将a函数的prototype指向指向b函数的实例 此时通过a函数实例出来的函数就可以根据原型链调用b函数的属性和方法
2.构造函数继承
通过.call方法 相当于拷贝a函数的实例属性给b函数 这种继承方式 b函数的实例的原型链上没有a函数

防抖节流

防抖和节流都是应用在高频触发的事件中
1.防抖是当事件高频触发的时候只执行最后一次
2.节流是当事件高频触发的时候会按照设置的固定频率执行多次,稀释触发频率

什么是跨域 为什么会发生跨域 以及跨域的解决方案

跨域:

浏览器从一个域名的网页去请求另一个域名的资源是,域名,端口,协议任一不同都是跨域

为什么发生跨域:

跨域问题来自浏览器的同源策略 即只有 协议+主机名+端口号相同 则允许相互访问
跨域问题是针对js和ajax的,html本身是没有跨域问题,比如

可以直接跨域发送并接受数据

解决跨域的方案

1.跨域资源共享CORS:
需要浏览器和后端同时支持,但实现 CORS 通信的关键还是后端。
服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。
2.nginx反向代理:
实现原理类似于Node中间件 需要搭建一个中转nginx服务器,用于转发请求.
3.jsonp跨域
利用 标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以。

jsonp的工作原理

1.动态生成script标签 利用script可以跨域的特点,发起跨域的http请求 请求后端接口
2.后端接口返回的字符串很特殊,是一个符合js语法的函数调用,数据作为函数的实参传回客户端
3.后端返回的文本在作为js执行时会调用本地的函数,数据会传入函数由形参接受
jsonp的缺点
使用jsonp跨域时需要后端配合 (配置一个header头)
安全性不高
只能发起get请求

get 请求和 post 请求的区别

1、GET请求一般用去请求获取数据,

    POST一般作为发送数据到后台时使用

2、GET请求也可传参到后台,但是其参数在浏览器的地址栏的url中可见,所以隐私性安全性较差,且参数长度也是有限制的

    POST请求传递参数放在Request body中,不会在url中显示,比GET要安全,且参数长度无限制

3、GET请求刷新浏览器或回退时没有影响

    POST回退时会重新提交数据请求

4、GET 请求可被缓存

    POST 请求不会被缓存

5、GET 请求保留在浏览器历史记录中

   POST 请求不会保留在浏览器历史记录中

6、GET 请求可被收藏为书签

    POST 不能被收藏为书签

7、GET请求只能进行url编码(application/x-www-form-urlencoded)

    POST支持多种编码方式(application/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。)

8、GET请求比较常见的方式是通过url地址栏请求

    POST最常见是通过form表单发送数据请求
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。