js面试题

JavaScript013

js面试题,第1张

1.eventLoop

2.setTimeout 误差原因

3.深浅拷贝

4.跨域原因及解决方案

5.css放在头部,js放在尾部

6.css触发bfc

7.webpack plugin和loader区别

8.前端优化

9.协商缓存

10.长列表优化

11.webview交互

12.vue响应式原理

13.原型

14.算法题:数组中有n个元素,排列

EventLoop是计算机系统的运行机制,js就是运行这个机制,因为js是单线程语言,所以一旦遇到一个耗时很长的任务就会卡住,js为了解决这个问题就有了EventLoop

Event Loop是一个程序结构,用于等待和发送消息和事件。

就是在程序中有了两个线程,一个负责应用本身,主线程,另一个负责主线程和其它进程,称为EventLoop

1、js是单线程语言

基本数据类型存放在栈中的简单数据段

引用数据类型存放在堆中的对象

因为定时器是宏任务,如果执行栈的时间大于定时器花费的时间,那么定时器的回调在 宏任务(macrotask) 里,来不及去调用,所有这个时间会有误差。所以就会有误差

宏任务是宿主发起的比如script,setTimeout

css放在头部是因为页面加载html生成dom树的时候就可以同时对dom树进行渲染,防止闪跳,白屏

js放在尾部是因为js会修改dom树,需要一个稳定的dom树

BFC是css的一个布局概念,块级格式化上下文

浮动float不为none的时候

定位为position:absolute和fixed的

display的时候

overflow不为visible

解决浮动父元素坍塌问题

解决自适应布局的问题

解决外边距垂直方向重合问题

loader是文件加载器,运行在nodejs中,并对文件进行打包,压缩转换

plugin是插件,用于拓展webpack的功能

浅拷贝有两种定于,第一种是赋值,第二种是拷贝对象的第一层属性,深层还是一样的

深拷贝是指将对象拷贝一份,无论如何修改都不会改变原有的

响应式原理就是当数据发生改变的时候视图也会跟着更新

VUE是利用了Object.defineProperty的方法里面的setter 与getter方法的观察者模式来实现。

```

当查找一个对象的某个属性时,会先从它自身的属性上查找,

如果找不到的话会从它的_proto_属性上查找,就是这个构造函数的prototype属性,

如果还没找到就会继续在_proto_上查找,直到最顶层,找不到则为undefined,

像这样一层一层去查找形成一个链式的称为原型链

```

new一个函数,中间发生了什么

1.开辟一个内存空间,也就是创建一个空对象,obj={}或obj=new Object()

2.将这个新对象的_proto_属性指向它构造函数的prototype

3.将构造函数this绑定为这个新对象,在空对象上挂在属性和方法(call或apply方式)

4.返回这个新对象

相同:都是改变函数上下文this指向

不同:bind返回的是一个函数,不会立即执行

         传参的不同 apply第二个参数为数组形式

         call apply都是对函数的直接调用

1.作为普通函数直接调用,this指向window

2.作为对象方法去调用的话,this指向调用它的这个对象

3.箭头函数,没有this,this取决于外层离它最近的非箭头函数的this

4.构造函数的this,指向创建这个构造函数的实例对象

1.词法作用域(静态作用域)

  js采用的就是词法作用域

  只有函数可以限定作用域

  函数允许函数访问外层作用域的变量

  函数在定义的时候决定了函数作用域,词法作用域关心函数在何处被定义

2.动态作用域

  函数在调用的时候决定了函数作用域,动态作用域关心函数在何处被调用

变量取值会到创建这个变量的函数作用域中去查找,如果找不到会向上查找,直到查找到全局作用域,这就形成了一个作用域链

1.节流

2.防抖

1.原型链继承

2.构造函数继承

3.组合继承(原型链继承+构造函数继承)

4.原型式继承

5.寄生继承

6.组合寄生继承

定义在一个函数内部的函数,这个内部函数有权访问外部函数作用域的变量

优点:

缺点:

js在运行中的任务,有一套收集,排队,执行的特殊机制,这种机制就是事件循环

遇到同步事件直接执行,遇到异步事件分为宏任务和微任务

如果微任务列表里有任务,先执行微任务再执行宏任务

块级作用域  暂时性死区  能否被修改

没有this  call apply方法修改this无效

没有prototype属性

没有argument

不能使用new  不能用作构造函数,会报错

持续更新中.......

数组扁平化定义:在前端项目开发过程中,偶尔会出现层叠数据结构的数组,需要把多层数组转换为一级数组(即提取嵌套数组元素最终合并为一个数组),使其内容合并并且展开。

遍历数组的方案:

for循环

for...of

for...in

forEach()

entries()

keys()

values()

reduce()

map()

判断元素是否是数组的方案:

instanceof

constructor

object.prototype.toString.call

isArray

将数组元素进行展开一层的方案:

扩展运算法 + concat(concat() 方法用于合并两个或多个数组,在拼接的过程中加上扩展运算符会展开一层数组)

concat + apply(主要是利用 apply 在绑定作用域时,传入的第二个参数是一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。也就是在调用 apply 函数的过程中,会将传入的数组一个一个的传入到要执行的函数中,也就是相当对数组进行了一层的展开。)

toString + split(不推荐使用 toString + split 方法,因为操作字符串是很危险的事情,如果数组中的元素所有都是数字的话,toString + split 是可行的,并且是一步搞定。)

最终手写的flat()方法为:

参考博客如下,注明一下出处,感谢大神们,希望自己可以多多练习,多多回顾:

三元博客

JS数组reduce()方法详解及高级技巧

数组flat方法实现