渲染页面6、连接结束(断开连接过程是四次挥手的过程)

  4、服务器处理请求并返回HTTP报文

  5、浏览器解析渲染页面

  6、连接结束(断开连接过程是四次挥手的过程)

  8、Promise构造函数是同步执行还是异步执行,那么 then 方法呢?

  Promise构造函数是同步执行的,then方法是异步执行的

  9、setTimeout、Promise、async/await 的区别?

  事件循环(EventLoop)中分为宏任务队列和微任务队列

  setTimeout的回调函数放到宏任务队列里,等到执行栈清空以后执行

  promise.then里的回调函数会放到相应宏任务的微任务队列里,等宏任务里面的同步代码执行完再执行

  async函数表示函数里面可能会有异步方法,await后面跟一个表达式。async方法执行时,遇到await会立即执行表达式,然后把表达式后面的代码放到微任务队列里,让出执行栈让同步代码先执行

  补充:promise是es6新增一种异步编程的方案

  async/await是es7中新增的异步编程的方案。

  经典案例:今日头条的面试题,执行的顺序

  <pre class="has">async function async1 () {  console.log(&#39;async1 start&#39;) // 2  await async2(); console.log(&#39;async1 end&#39;)    //7}async function async2 () {  console.log(&#39;async2&#39;)      //3}console.log(&#39;script start&#39;) // 1setTimeout(function () {  console.log(&#39;setTimeout&#39;)   //8}, 0)async1();new Promise (function (resolve) {  console.log(&#39;promise1&#39;)   //4   resolve();}).then (function () {  console.log(&#39;promise2&#39;)  //6})console.log(&#39;script end&#39;) //5运行结果:1、 script start2、 async1 start3、 async24、 promise15、 script end6、 promise27、 async1 end8、 setTimeout</pre>

  10、forEach、for in、for of三者区别

  forEach:用来遍历数组,对数组中的每个元素执行一次提供的函数,不改变原数组,无返回值,undefined。

  for in 一般常用来遍历对象或json。

  for of数组对象都可以遍历。其中遍历对象使用Object.keys()

  例:arr.forEach(function(value,index,arr){代码段})

  例:let obj={a:1,b:2} for(let o in obj){console.log(o) //a b }

  例:letarr=[‘China’,’korea’] let obj={a:1,b:2}

  for(let o of arr){console.log(o) // China Korea}

  for(let o of Object.keys(obj)){//直接写for(let o of obj)报错

  console.log(o) }// ab 对象中的键

  11、手写一个Promise(中高级必考)什么是promise?promise是用来干啥的?解决了什么问题?

  Promise是异步编程的一个解决方案,主要用来解决两个问题:1、解决异步的问题,2、解决回调地狱的,就是第一个函数的输出是第二个函数的输入的这种现象。

  <pre class="has">let promise=new Promise((resolve,reject)=>{If(异步操作成功){resolve(value);}else{reject(error); //操作失败}})promise.then(function(value){ //success },function(error){ //failure }) //promise.then()两个参数,第二个参数可选</pre>

  Promise对象的三种状态:pending(正在进行)、fulfilled(成功)、rejected(失败)。

  状态只能pending到fulfilled或者pending到rejected,状态一旦改变不能再变。

  12、对象、数组的深拷贝浅拷贝

  浅拷贝:就是流于表面的拷贝方式,浅拷贝只拷贝的对象的地址,也就是说两个对象指向的是同一地址,修改其中的一个对象的属性,另一个对象的属性也会修改。

  深拷贝:完全拷贝,拷贝之后新旧数据完全分离,不再共用对象类型的属性值,不会相互影响。

  13、手写一个js深拷贝(先理解什么是深拷贝)

  乞丐版:

  <pre class="has">01、var newObj=JSON.parse(JSON.stringify(obj))无法复制函数,丢失原型链,对于多维数组也有效02、var newArr=arr.slice() 或者arr.concat() 只能实现一维数组的深拷贝03、var […newArr]=arres6扩展运算法实现数组的深拷贝(当然数组中没有属性值没有对象的时候)04、var {…obj2}=obj05、对象只有一层的话可以使用Object.assign()函数var newobj=Object.assign({},obj)</pre>

  面试够用版(判断是数组还是对象,新建一个数组或者对象,通过forin循环数组对象,完成深拷贝)递归拷贝

  <pre class="has">function deepCopy(obj){     //判断是否是简单数据类型if(typeof obj == "object"){    //复杂数据类型         var result = obj.constructor == Array ? [] : {};         for(let i in obj){              result[i] = typeof obj[i] == "object" ?deepCopy(obj[i]) : obj[i];   }      //递归判断 }else {    //简单数据类型 直接 == 赋值         var result = obj;     }     return result;}</pre>

  14、数组去重手写

  利用es6中Set去重

  <pre class="has">var arr = [1,2,2,23,23,undefined,undefined]; var newarr = Array.from(new Set(arr)) console.log(newarr) // [1, 2, 23, undefined]补充:ES6提供了一个新的数据结构Set,本身是一个构造函数,用来生成Set的数据结构。类似于数组,但是成员的属性都是唯一的,没有重复的值。</pre>

  双重for循环+splice()方法

  <pre class="has">function single(arr){ for(var i=0;i for(var j=i+1;j if(arr[i]==arr[j]){ arr.splice(j,1); j--;  //arr的长度变了 } }} return  arr;}var arr = [1,2,2,23,23,undefined,undefined];     console.log(single(arr)) // [1, 2, 23, undefined]</pre>

  利用indexOf去重

  <pre class="has">var arr = [1,2,2,23,23,undefined,undefined]; var newapp=[];for(var i=0;iif(newapp.indexOf(arr[i])===-1){newapp.push(arr[i])}} console.log(newapp) // [1, 2, 23, undefined]</pre>

  新建一个空数组,for循环判断新数组中是否存在原数组中元素,如果有相同的值则跳过,不相同push到新数组。

  15、冒泡排序和选择排序

  冒泡排序:相邻两个元素比较

  相邻两个元素进行比较,将一个数组中数字使用循环进行升序或排序的

  <pre class="has"> arr = [1, 2, 3, 4] for (var j = 0; j < arr.length; j++) { for (var i = 0; i < arr.length; i++) { if (arr[i] < arr[i + 1]) { var a = arr[i] arr[i] = arr[i + 1] arr[i + 1] = a; } } }</pre>

  选择排序:先找值

  这种排序方式先找最大的,排在最左侧,然后找第二个往左靠。。。。

  <pre class="has">arr = [1, 2, 3, 4] for (var i = 0; i < arr.length - 1; i++) { for (var j = i + 1; j < arr.length; j++) { if (arr[i] < arr[j]) { tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } } }</pre>

  冒泡排序和顺序排序(划重点)。

  (1)冒泡排序是比较相邻位置的两个数,而选择排序是按顺序比较,找最大值或者最小值;

  (2)冒泡排序每一轮比较后,位置不对都需要换位置,选择排序每一轮比较都只需要换一次位置;

  (3)冒泡排序是通过数去找位置,选择排序是给定位置去找数;

  总结:一般选择排序优于冒泡排序。因为每次排序只需要交换一位置。冒泡排序比较耗性能。

  16、浅谈async/await

  1、async声明一个异步asyncfunction fun(){….}

  自动将常规的函数转换成Promise ,返回值也是一个Promise对象。

  只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数。

  异步函数内部可以使用await

  2、await等待异步功能执行 varresult=awaitnewPromise()

  放置在Promise调用之前js 递归遍历多维数组,await强制其他代码等待,直到Promise完成并返回结果

  只能与Promise一起使用,不适于回调。

  只能在async函数内部使用。

  17、事件循环

  <pre class="has">function printing() { console.log(1); setTimeout(function() { console.log(2); }, 1000); setTimeout(function() { console.log(3); }, 0); console.log(4); } // 1 4 3 2</pre>

  理解:javascritpt是一门单线程的语言。

  js分为同步任务和异步任务。事件循环分为宏任务和微任务。

  同步任务在主线程上执行,形成一个执行栈,主线程之外,事件触发线程管理着一个任务队列,只要异步任务有了运行结果,就在任务队列中放置一个事件。

  一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列,将可执行的异步任务添加到执行栈中,开始执行。

  执行顺序:执行栈中的任务----事件循环中宏任务------事件循环中的微任务

  同步任务交给主线程,主线程之外事件触发线程管理一个任务队列,为异步任务。

  18、ajax请求的时候get 和post方式的区别

  1、get请求会将参数跟在url后面进行参数传递,而post请求则是作为http消息的实体内容发送给web服务器。

  2、get提交的数据大小有限制,这个限制是url的整体长度而不是参数的长度。post提交没有这个限制。

  3、get请求的数据会被浏览器缓存起来,带来严重的安全问题,而post相对来说可以避免这些问题。

  4、一般情况下。Get请求用来请求数据,post请求用来提交数据。

  19、Javascript垃圾(GC)回收机制

  Javascript垃圾回收机制原理:为了防止内存泄漏,垃圾回收机制会定期的清理哪些不再用到内存变量,然后释放其内存。

  现在各大浏览器的通常采用的垃圾回收机制的两种方法:标记清除、引用计数

  Js最常用的垃圾回收方式是标记清除,当变量进入环境时,将这个变量标记为“进入环境”,当这个变量离开环境时标记“离开环境”。标记为‘离开环境’的就回收内存。

  20、闭包是什么,有什么特性,对页面有什么影响

  闭包是指有权访问另—个函数作用域中变量的函数。创建闭包的最常见的方式就是在—个函数内创建另—个函数,通过另—个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。

  闭包的特性:

  1.函数内再嵌套函数

  2.内部函数可以引用外层的参数和变量

  3.参数和变量不会被垃圾回收机制回收,使变量私有化,容易造成内存的泄漏。

  21、”==”和“===”的不同

  前者会自动转换类型,再判断是否相等,后者不会自动类型转换,直接去比较

  22、函数声明与函数表达式的区别?

  定义函数的三种方式1、函数声明2、函数表达式3、new Function构造函数。

  在Javscript中,解析器在向执行环境中加载数据时,对函数声明和函数表达式并非是一视同仁的,解析器会率先读取函数声明(函数提升),并使其在执行任何代码之前可用(可以访问),至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解析执行。

  hello()

  functionhello(){

  console.log(“函数的声明”)

  }

  fun() //这里会报错!

  var fun=function(){

  console.log(“函数表达式”)

  }

  23、null和undefined的区别?

  null是一个表示"无"的对象,转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为NaN。当声明的变量还未被初始化时,变量的默认值为undefined。null用来表示尚未存在的对象

  js多维数组遍历_js 递归遍历多维数组_js 递归遍历多维数组

  undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。典型用法是:

  (1)变量被声明了,但没有赋值时,就等于undefined。

  (2)调用函数时,应该提供的参数没有提供,该参数等于undefined。

  (3)对象没有赋值的属性,该属性的值为undefined。

  (4)函数没有返回值时,默认返回undefined。

  null表示"没有对象",即该处不应该有值。典型用法是:

  (1) 作为函数的参数js 递归遍历多维数组,表示该函数的参数不是对象。

  (2) 作为对象原型链的终点。

  24、new操作符具体干了什么呢?(面对对象)

  1、创建一个空对象

  2、将构造函数中的this指向这个对象

  3、将属性和方法绑定到这个对象上

  4、隐式返回这个对象

  25、如何获取javascript三个数中的最大值和最小值?

  Math.max(a,b,c);//最大值

  Math.min(a,b,c)//最小值

  Math.max(…arr) //arr是一个数组[2,5,66,7] 返回66 扩展符

  26、闭包的优点:(32特点)

  (1)希望一个变量长期驻扎在内存当中(不被垃圾回收机制回收)

  (2)避免全局变量的污染

  (3)私有成员的存在

  27、如何优化网页加载速度?

  1、压缩 css和 Js 代码 ,减少css和js的文件大小

  2、合并js、css文件,减少http请求

  3、将css样式放在顶部,将js脚本放在底部

  4、减少DOM操作,尽可能的用变量代替不必要的dom操作。

  5、使用外部的js和css。

  28、你如何优化自己的代码?

  1、代码重用:

  2、避免全局变量(命名空间,封闭空间,模块化mvc..)

  3、拆分函数避免函数过于臃肿

  4、适当的注释

  5、变量命名规范

  6、内存管理,尤其是闭包中的变量的释放。

  js 递归遍历多维数组_js 递归遍历多维数组_js多维数组遍历

  29、重绘和回流(重排)

  回流(重排):

  1、当render tree 中的一部分(或全部)因为元素的规模尺寸,布局、隐藏等改变而需要重新构建,这就称为回流

  2、当页面布局和几何属性改变时就需要回流

  什么是重绘?

  1、当render tree 中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就称为重绘。

  回流必将引起重绘,而重绘不一定会引起回流

  30、栈和堆的区别?

  栈(stack):由编译器自动分配释放,存放函数的参数值,局部变量等;

  堆(heap):一般由程序员分配释放,若程序员不释放,程序结束时可能由操作系统释放

  31、Javascript作用链域

  作用域链的原理和原型链很类似,如果这个变量在自己的作用域中没有,那么它会寻找父级的,直到最顶层。

  注意:JS没有块级作用域,若要形成块级作用域,可通过(function(){})();立即执行的形式实现

  32、谈谈this的理解-------(this永远指向最后调用它的对象,也就是执行的时候谁调用的)

  01、普通函数中的this代表window。

  02、事件中的this代表的事件源(特殊IE浏览器attchEvent中的this总指向去全局对象window)

  03、定时器中函数代表的window

  04、自调用的函数中额this指向window

  05、对象中的方法中this的代表的是当前对象

  06、箭头函数中this指向定义时的上一层作用域中this

  (补充:箭头函数本身没有this和arguments的,在箭头函数中引用this实际上是调用定义时的上一层作用域的this。这里强调是上一层的作用域,是因为对象是不能形成独立作用域的。)

  33、es5和es6的区别,说一下你所知道的es6

  ES6新增的一些特性:

  01、声明变量的关键字:let、const-------两个都有块级作用域且var有变量提升。

  02、箭头函数

  03、模板字符串------模板字符串是增强版的字符串,用反引号(`)标识,可以当作普通字符串使用,也可以用来定义多行字符串

  04、 解构赋值--------ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值

  05、for of循环--------for...of循环可以遍历数组、Set和Map结构、某些类似数组的对象、对象,以及字符串

  06、import、export导入导出----在es6中文件可以默认为一个模块,模块通过export向外暴露接口。通过import导入一个模块,注意import和export只能出现在模块的最外层结构中能够,否则报错。

  07、Set数据结构----Set数据结构类似数组,所有的数据都是唯一的,没有一个重复值,它本身是一个构造函数。

  08、展开运算符----…

  09、class类的继承---ES6中不再像ES5一样使用原型链实现继承,而是引入class这个概念

  10、Promise------es6提供的一个异步编程的方案。

  11、Proxy代理------使用代理监听对象的操作

  js多维数组遍历_js 递归遍历多维数组_js 递归遍历多维数组

  12、修饰器------decorator是一个函数,用于修改类似与方法的行为

  13、Symbol-----新的原始数据类型。Symbol 通过调用symbol函数产生,它接收一个可选的名字参数,该函数返回的symbol是唯一的

  34、var、let、const之间的区别

  var声明变量可以重复声明,而let不可以重复声明

  var是不受限于块级的,而let是受限于块级

  var会与window相映射(会挂一个属性),而let不与window相映射

  var可以在声明的上面访问变量,而let有暂存死区,在声明的上面访问变量会报错

  const声明之后必须赋值,否则会报错

  const定义不可变的量,改变了就会报错

  const和let一样不会与window相映射、支持块级作用域、在声明的上面访问变量会报错

  35、使用箭头函数应注意什么?

  (1)箭头函数中的this,不是指向window,而是父级。

  (2)不能使用arguments对象(箭头函数中没有this和arguments对象)

  (3)不能用作构造函数,就是不能使用new命令,否则会跑出错误。

  (4)不可以使用yeild命令。因此箭头函数不能用作Generator函数

  (补充:Generator函数作为一个用来操作异步的状态机,遇到yeild停止,通过调用next()来继续操作,一:function关键字与函数名之间有一个星号,函数体使用yeild(类似return)产出不同的状态。)

  36、ECMAScript 6 怎么写 class ,为何会出现 class?

  ES6的class可以看作是一个语法糖,它的绝大部分功能ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法

  <pre class="has">class Person{constructor(name){         this.name=name  //this关键字代表实例对象 } say(){      console.log(123) }}var person =new Person(‘张三’);person.say()</pre>

  37、说一下es6的导入导出模块

  导入通过import关键字

  import {sum} from "./example.js" 导入一个模块中一个成员

  import {sum,multiply,time} from "./exportExample.js" //导入多个

  import * as example from "./exportExample.js" //导入一整个模块

  导出通过export关键字

  export var name= 'Michael';

  export {firstName, lastName, year};

  使用export default时,对应的import语句不需要使用大括号

  let bosh = function crs(){ }

  export default bosh; //导出

  import crc from 'crc'; //导入

  不使用export default时,对应的import语句需要使用大括号

  let bosh = function crs(){ }

  export bosh; //导出

  import {crc} from 'crc'; //导入

  在es6中文件可以默认为一个模块,模块通过export向外暴露接口。通过import导入一个模块,注意import和export只能出现在模块的最外层结构中能够,否则报错。

  Export default向外暴露成员只允许一次

文章由官网发布,如若转载,请注明出处:https://www.veimoz.com/1401
0 评论
342

发表评论

!