web前端-JS面试题总结
小职 2021-12-12 来源 :Attacking-Coder 阅读 385 评论 0

摘要:本篇主要是web前端-JS面试题总结,通过具体的内容展现,希望对大家web前端学习以及前端开发面试有所帮助。

本篇主要是web前端-JS面试题总结,通过具体的内容展现,希望对大家web前端学习以及前端开发面试有所帮助。

web前端-JS面试题总结


js的数据类型

基本数据类型(6个):number、string、boolean、null、undefined、symbol

引用数据类型(2个):Array、Object


如何判断简单数据类型(typeof)

    typeof "123"  => "string"

    typdof 123    => "number"

    typeof true   => "boolean"

    typeof null   => "object"

    typeof undefined  => "undefined"

    `可以看出 typeof 对于引用数据类型不好用`

    typeof [1,2,3]   => "object"

    typeof {name:'zs'}   => "object"

    typeof 函数 => "function"


如何判断引用数据类型

1.Array.isArray() 判断该实例对象是不是数组

2.a instanceof b 判断该a实例对象是不是属于b这个构造函数

3.a.constructor 判断a的构造函数是什么


   var a = [1,2,3];

   var b = {

       name:'zs'

   }


Array.isArray()

console.log( Array.isArray(a))//true

console.log( Array.isArray(b))//false


instanceof(原理)

原理:

A instanceof B

instanceof用于检测对象A是不是对象B的实例,而检测是基于原型链进行查找的,也就是说对象B的prototype有没有在对象A的__proto__原型链上,如果有就返回true,,否则返回false


console.log(a instanceof Array);//true

console.log(b instanceof Object);//true


constructor

console.log(a.constructor == Array);//true

console.log(b.constructor == Object);//true


原型链

什么是原型链

每个对象拥有一个原型对象,通过 proto 指针指向其原型对象,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向 null(Object.proptotype.__proto__指向的是null)。这种关系被称为原型链(prototype chain),通过原型链一个对象可以拥有定义在其他对象中的属性和方法


构造函数有一个prototype属性,这个属性是一个指针 指向他的原型对象

原型对象下的属性和方法  可以被实例化对象所共享 

原型对线下有一个constructor 属性指向他的构造函数

实例化对象下边有个__proto__属性指向构造函数的原型对象

web前端-JS面试题总结



继承(es6之前)

父类Person


  function Person(name,age){

      this.name = name;

      this.age = age;

  }

  Person.prototype.say = function(){

      console.log(this.name +"haha");

  }



子类Coder


  function Coder(name,age){

      // this

      // call方法可以改变this指向

      Person.call(this,name,age);

  }

  // 继承父类的方法  

  // 不可以Coder.prototype = Person.prototype; 因为这样后边在更改constructor属性指向时会把Person.prototype.constructor一起更改

  Coder.prototype = new Person();

  // 此时Coder的原型对象下的constructor属性 指向Person  所以要再给他指回Coder

  Coder.prototype.constructor = Coder;


this指向问题

this一般指向函数的调用者

web前端-JS面试题总结

怎么改变this指向(call、apply、bind)

在函数后边调用这三个方法


call(thisArg,a,b,c)

apply(thisArg,[a,b,c])

bind(thisArg,a,b,c)

其中:thisArg代表你想要this指向的东西

a b c代表函数要的参数


call、apply、bind的不同

call和apply会直接调用函数,使函数执行。而bind不会直接执行函数,只会改变函数的this指向

call和bind的传参都是a,b,c。而apply传递参数则是需要用数组[a,b,c]

事件源和事件处理函数中this的区别

事件源是指触发了事件处理函数的源头

而this指向的是绑定了处理函数的对象


乍一听二者可能没啥区别!那么请看下边代码


  <div id="div1">

      div1

      <div id="div2">

          div2

      </div>

  </div>


  #div1{

      width: 200px;

      height: 200px;

      background: #ff0000;

  }

  #div2{

      width: 100px;

      height: 100px;

      background: #0000ff;

  }


  var oDiv = document.getElementById('div1');

  oDiv.onclick = function(e){

      console.log('哈哈哈哈');

      // 事件源 

      console.log(e.target);

      // this 对当前对象引用 

      console.log(this);

  }


此时我们点击div1得到如下输出

web前端-JS面试题总结

我们再点击一下div2,由于事件冒泡点击div2同样会触发div1的点击事件。得到如下输出

web前端-JS面试题总结


结论

事件源(e.target)指的是触发了这个事件的罪魁祸首

this指的是事件函数所绑定的那个对象


事件冒泡和事件捕获

事件冒泡

就和水壶烧水一样,气泡是从内部像外部移动的。类比到事件冒泡就是点击内部子元素除了会触发自己本身的点击事件同时也会逐级触发祖先元素的点击事件。


事件捕获

就和俄罗斯套娃一样,你想摸最里边的,就得依次经历外边基层的套娃。点击子元素会先触发最外层的父元素然后逐级向里触发子元素


当事件冒泡与事件捕获同时存在

它会先进行事件捕获,然后再进行事件冒泡


代码与结果如下:


 <div id="div1">

     div1

     <div id="div2">

         div2

     </div>

 </div>

 

 #div1 {

     width: 200px;

     height: 200px;

     background: #ff0000;

 }


 #div2 {

     width: 100px;

     height: 100px;

     background: #0000ff;

 }


 var oDiv1 = document.getElementById('div1');

 var oDiv2 = document.getElementById('div2');


 // 同时有冒泡和捕获的时候  先捕获 再冒泡 (先从外到里,再从里往外)


 oDiv1.addEventListener('click', function () {

     console.log('div1 捕获');

 }, true);


 oDiv2.addEventListener('click', function () {

     console.log('div2 捕获');

 }, true);


 oDiv1.addEventListener('click', function () {

     console.log('div1 冒泡');

 }, false);


 oDiv2.addEventListener('click', function () {

     console.log('div2 冒泡');

 }, false);


点击div2后

web前端-JS面试题总结


事件委托

通过事件冒泡和事件源的配合,来解决后生成元素的事件绑定问题


例子如下所示

下面的代码for循环只给前三个li进行了点击事件的绑定,而通过button点击生成的新li并没有点击事件


 <button id="btn">click</button>

 <ul id="ul1">

     <li>11111</li>

     <li>22222</li>

     <li>33333</li>

 </ul>


  li{

      background: #ff0000;

  }


  var aLi = document.getElementsByTagName('li');

  var oBtn = document.getElementById('btn');

  var oUl = document.getElementById('ul1');

  for(var i=0; i<aLi.length; i++){

      aLi[i].onclick = function(){

          console.log(this.innerHTML);

      }

  }

  oBtn.onclick = function(){

      var oLi = document.createElement('li');

      oLi.innerHTML = Math.random();

      oUl.appendChild(oLi);

  }


通过事件委托改造后的代码,可以实现新生成的li也有点击事件


 <button id="btn">click</button>

 <ul id="ul1">

     <li>11111</li>

     <li>22222</li>

     <li>33333</li>

 </ul>


  li{

      background: #ff0000;

  }


  var aLi = document.getElementsByTagName('li');

  var oBtn = document.getElementById('btn');

  var oUl = document.getElementById('ul1');


  oBtn.onclick = function(){

      var oLi = document.createElement('li');

      oLi.innerHTML = Math.random();

      oUl.appendChild(oLi);

  }


  oUl.onclick = function(e){

      // console.log(e.target.tagName)

      if(e.target.tagName == "LI"){

          console.log(e.target.innerHTML);

      }

  }


闭包

内部函数可以访问外部函数的变量(也包括外部函数的参数)


作用:

避免了对全局变量的污染

可以是一个变量长期驻扎在内存之中

缺点:

容易发生内存泄漏


例子

function fn1(val){

// 这个a会一直保存在内存中因为你也不知道啥时候还回调用内部返回的这个function

var a = 20;

return function(){

a++;

console.log(a,val);

}

}

var f = fn1();

f();

f();

f();


<ul>

<li>1111</li>

<li>222</li>

<li>3333</li>

</ul>

var aLi = document.getElementsByTagName('li');

for(var i=0; i<aLi.length; i++){

(function(i){

// i是外部函数中的参数

aLi[i].onclick = function(){

console.log(i);

}

})(i);

}


节流

如果某个函数需要频繁触发,出于性能优化考虑,在规定时间内只让函数的第一次生效


例子

  // 闭包  this

  function throttle(fn,delay){

      var startTime = 0;

      // 这个return的函数this指向的是事件绑定的那个对象

      return function(){

          var nowTime = Date.now();

          if(nowTime - startTime > delay){

              fn.call(this);

              startTime = nowTime;

          }

      }

  }


  document.onmousemove = throttle(function(){

      console.log(Date.now())

      console.log(this);

  },1000);


防抖

一个需要频繁触发的函数,在规定时间内只让最后一次生效,前面的都不生效


例子

    <button id="btn">点击</button>


    <script>


        var btn = document.querySelector('#btn')

// 用闭包技术存储timer,防止污染全局变量

        function fangdou(fn, delay) {

            var timer = null

            return function () {

                clearTimeout(timer)

                timer = setTimeout(() => {

                 // 因为fn是一个普通函数所以他的this指向的是window,为了让他的this指向绑定事件的对象便用call来改变this指向

                    fn.call(this)

                }, delay)

            }

        }


        btn.onclick = fangdou(function () {

            console.log(this)

        }, 300)


    </script>


同步任务与异步任务(js是单线程的)

同步任务

在主线程上排队执行的任务,只有前一任务执行完后面的任务才可以依次执行。


异步任务

不进入主线程,而是进入任务队列的任务,只有当主线程全部执行完了才会去看任务队列中是否有异步任务可以开始执行了。如果有则把该异步任务拉到主线程进行执行


事件循环

在所有同步任务都在主线程上执行,形成一个执行栈

主线程之外,还存在一个任务队列。只要异步任务有了运行结果,就在任务队列之中放置一个事件

一旦执行栈中所有的同步任务都执行完毕,系统就会读取任务队列,看看里边有哪些事件。那些对应的异步任务,就会进入执行栈,开始执行。

主线程不断重复第三个步骤

web前端-JS面试题总结


任务队列分为:宏任务和微任务

宏任务:包括整体代码script,setTimeout,setInterval,setImmediate

宏任务所处的队列称为宏任务队列

宏任务队列可以有多个

微任务:包括new Promise.then(回调),process.nextTick

微任务所处的队列称为微任务队列

只有一个微任务队列

总结:执行栈会先看微任务队列有没有任务,然后才会去看宏任务队列。


例子

console.log('1');


setTimeout(function() { //1-宏任务

    console.log('2');

    process.nextTick(function() { //2-1微任务

        console.log('3');

    });

    new Promise(function(resolve) {

        console.log('4');

        resolve();

    }).then(function() {  //2-2微任务

        console.log('5')

    });

})

process.nextTick(function() { //1-微任务

    console.log('6');

})

// 1 6 2 4 3 5


结果:

web前端-JS面试题总结


AJAX原理

    存有 XMLHttpRequest 的状态(就是下边代码的readyState属性)。从 0 到 4 发生变化。

    0: 请求未初始化

    1: 服务器连接已建立

    2: 请求已接收

    3: 请求处理中

    4: 请求已完成,且响应已就绪


    status(就是下边代码的status属性)

    200   (“OK”)  成功 一切正常

    500   服务器方面的问题

    503 (服务不可用)

    404   找不到资源

    301  永久重定向

    302  临时重定向

    304  缓存


什么是重定向


GET请求示例

        //创建 XMLHttpRequest 对象

        var xmlhttp;

        if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari

            xmlhttp = new XMLHttpRequest();

        } else { // code for IE6, IE5

            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

        }

        // 向服务器发送GET请求  请求方式  url 是否异步

        // get请求时候参数写在接口地址后边就行

        xmlhttp.open("GET", "test1.txt?name=zs", true);

        xmlhttp.send();

        

        // 服务器响应 异步的

        xmlhttp.onreadystatechange = function () {

            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {

                console.log(xmlhttp.responseText);

            }

        }


POST请求示例

        //创建 XMLHttpRequest 对象

        var xmlhttp;

        if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari

            xmlhttp = new XMLHttpRequest();

        } else { // code for IE6, IE5

            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

        }

        // post  请求方式  url  是否异步

        xmlhttp.open("POST","ajax_test.asp",true);

        // 设置请求头 "Content-type","application/x-www-form-urlencoded"说明post传给后台的数据是表单(form)数据

        xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");

        // post请求时候参数写在send中

        xmlhttp.send("fname=Bill&lname=Gates");

        

        // 服务器响应 异步的

        xmlhttp.onreadystatechange = function () {

            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {

                console.log(xmlhttp.responseText);

            }

        }


es6新特性

let var const区别***

let、const同var的区别

let和const没有变量提升

let和const不可以重复声明同一个变量

let和const具有块级作用域

let和const有暂时性死区

例子:

<!DOCTYPE html>

<html>


<head>

    <meta charset="UTF-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Document</title>

</head>


<body>

    <script>

        let a = 10

        function b() {

            console.log(a);

            let a = 15

            console.log(a);

        }

        b()

    </script>

</body>


</html>


web前端-JS面试题总结

这是因为let声明的变量在当前作用域下不允许同名的变量进来,又因为let不可以变量提升,所以函数中的第一次console.log(a)报错---------这就是所谓的暂时性死区


const独有的特性

const是定义常量的,如果是基本数据类型 就是不能变的,如果是对象的话,对象的存储地址(指针)是不能变的,属性值是可以变的,如果想让对象的值不能变的就Object.freeze(obj);这样值也是不能变的了


箭头函数

普通函数和箭头函数this指向上的区别:

(1)this指向问题


普通函数this是在调用的时候才能确定this指向

箭头函数this是在声明时候就已经确定了this指向,指向的是父作用域的this

(2)箭头函数不能用来当构造函数(也就是不能new)

(3)箭头函数不能使用arguments 可以使用…rest(这个叫做剩余参数)来替代


<!DOCTYPE html>

<html>


<head>

    <meta charset="UTF-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Document</title>

</head>


<body>


    <script>

        

        var a = (k, ...rest) => {

            console.log('k', k);

            console.log('rest', rest);

        }

        a(1, 2, 1, 3, 4, 5, 3, 1)


        function b() {

            console.log(arguments);

        }

        b(1, 2, 3, 1, 23, 2)

    </script>


</body>


</html>

web前端-JS面试题总结



箭头函数与普通函数的区别

this指向不同

call、apply、bind等方法不能改变箭头函数的this指向

箭头函数不可以作为构造函数

箭头函数没有自己的arguments.

箭头函数没有prototype

解构赋值

数组解构

web前端-JS面试题总结


函数解构


web前端-JS面试题总结

扩展运算符 …

把数组或者类数组展开成用逗号隔开的值


数组复制

const a1 = [1, 2];

const a2 = [...a1];


合并数组

let a1 = [1,2]

let a2 = [3,4]

let a3 = [1,4]


let a = [...a1, ...a2, ...a3] // [1, 2, 3, 4, 1, 4]


把类数组转化成数组

和解构赋值结合生成数组(扩展运算符参数必须在最后一位)

let [a1, ...list] = [1, 2, 3, 4, 5];

console.log(list) // [2, 3, 4, 5]


和set结构结合实现数组或字符串去重

let a1 = [1, 2, 3, 4, 1, 4];

// 数组去重

console.log([...new Set(a1)]) // [1, 2, 3, 4]

//字符串去重

console.log([...new Set('ababbc')].join('')) // abc


和解构赋值结合生成对象(扩展运算符参数必须在最后一位)

let { a, b, ...z } = { a: 1, b: 2, c: 3, d: 4 };

console.log(a) // 1

console.log(b) // 2

console.log(z) // { c: 3, d: 4 }


合并对象(多个对象有同名属性,则后面的会覆盖前面的)

let a1 = { a: 1, b: 2 };

let a2 = { a: 3, c: 4 };

let a3 = { ...a1, ...a2} // {a: 3, b: 2, c: 4} 可以发现a:1被覆盖掉了



resolve,reject,then,catch的用法

一个promise对象有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)

一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。

当你在new Promise()中调用了resolve()这时promise对象的状态pending变为fulfilled

当你在new Promise()中调用了reject()这时promise对象的状态pending变为rejected

当promise对象的状态为fulfilled时候,便会执行到.then()里边的函数,相反的当promise对象的状态为rejected时候,便会执行到.catch()里边的函数或者.then()里边的第二个函数


注意:then()和catch()就当做回调函数看待,他们前边的promise对象无论执行的多快,then和catch都会被放到执行队列中,等待执行栈全部执行完才会执行他俩

1

例子:


 function promiseClick() {

     let p = new Promise(function (resolve, reject) {

         setTimeout(function () {

             var num = Math.ceil(Math.random() * 20); //生成1-20的随机数

             console.log('随机数生成的值:', num)

             if (num <= 10) {

                 resolve(num);

             }

             else {

                 reject('数字太于10了即将执行失败回调');

             }

         }, 2000);

     })

     return p

 }


 promiseClick().then(

     function (data) {

         console.log('resolved成功回调');

         console.log('成功回调接受的值:', data);

     },

     function (reason) {

         console.log('rejected失败回调');

         console.log('失败执行回调抛出失败原因:', reason);

     }

 );


// 这个里边的catch就和上边那个then里的第二个函数一个作用

 promiseClick().then(

     function (data) {

         console.log('resolved成功回调');

         console.log('成功回调接受的值:', data);

     }

 ).catch(

     function (reason) {

         console.log('rejected失败回调');

         console.log('失败执行回调抛出失败原因:', reason);

     }

 )

web前端-JS面试题总结

web前端-JS面试题总结

all和race的用法

all

只有当所有的promise对象状态都是fulfilled时候,all才会返回一个fulfilled的promise对象,否则返回的都是rejected的promise对象


例子1


        function promiseClick1() {

            let p = new Promise(function (resolve, reject) {

                setTimeout(() => {

                    resolve(1)

                }, 1000)

            })

            return p

        }

        function promiseClick2() {

            let p = new Promise(function (resolve, reject) {

                setTimeout(() => {

                    resolve(12)

                }, 2000)

            })

            return p

        }

        function promiseClick3() {

            let p = new Promise(function (resolve, reject) {

                setTimeout(() => {

                    resolve(123)

                }, 3000)

            })

            return p

        }


        Promise.all([promiseClick1(), promiseClick2(), promiseClick3()]).then(data => {

            console.log('三个promise对象状态都是fulfilled');

            console.log(data);

        })


例子2


        function promiseClick1() {

            let p = new Promise(function (resolve, reject) {

                setTimeout(() => {

                    resolve(1)

                }, 1000)

            })

            return p

        }

        function promiseClick2() {

            let p = new Promise(function (resolve, reject) {

                setTimeout(() => {

                    resolve(12)

                }, 2000)

            })

            return p

        }

        function promiseClick3() {

            let p = new Promise(function (resolve, reject) {

                setTimeout(() => {

                    reject(123)

                }, 3000)

            })

            return p

        }


        Promise.all([promiseClick1(), promiseClick2(), promiseClick3()]).then(data => {

            console.log('三个promise对象状态都是fulfilled');

            console.log(data);

        }).catch((res) => {

            console.log('三个promise对象肯定有状态不是fulfilled');

            console.log(res);

        })

web前端-JS面试题总结

race

race是只要有一个promise对象完事了,就按照这个promise对象的状态返回一个promise对象。其余的promise对象一概不理会


例子1


        function promiseClick1() {

            let p = new Promise(function (resolve, reject) {

                setTimeout(() => {

                    resolve(1)

                }, 1000)

            })

            return p

        }

        function promiseClick2() {

            let p = new Promise(function (resolve, reject) {

                setTimeout(() => {

                    resolve(12)

                }, 2000)

            })

            return p

        }

        function promiseClick3() {

            let p = new Promise(function (resolve, reject) {

                setTimeout(() => {

                    resolve(123)

                }, 3000)

            })

            return p

        }


        Promise.race([promiseClick1(), promiseClick2(), promiseClick3()]).then(data => {

            console.log('fulfilled', data);

        }).catch((res) => {

            console.log('rejected', res)

        })

web前端-JS面试题总结



例子2


        function promiseClick1() {

            let p = new Promise(function (resolve, reject) {

                setTimeout(() => {

                    // 这里和例子1不同

                    reject(1)

                }, 1000)

            })

            return p

        }

        function promiseClick2() {

            let p = new Promise(function (resolve, reject) {

                setTimeout(() => {

                    resolve(12)

                }, 2000)

            })

            return p

        }

        function promiseClick3() {

            let p = new Promise(function (resolve, reject) {

                setTimeout(() => {

                    resolve(123)

                }, 3000)

            })

            return p

        }


        Promise.race([promiseClick1(), promiseClick2(), promiseClick3()]).then(data => {

            console.log('fulfilled', data);

        }).catch((res) => {

            console.log('rejected', res)

        })

web前端-JS面试题总结



async

1.async定义的函数是异步函数,也就是说它不会阻塞其后边代码的执行。

2.async定义的函数返回的是一个promise对象。当你return一个值的时候他就会返回一个状态为fulfilled的promise对象,当你throw一个值的时候他就会返回一个状态为rejected的promise对象。


  async function a(flag) {

      if (flag) {

          return '我是真滴帅'

      } else {

          throw '报错了'

      }

  }

  console.log(a(true))

  console.log(a(false));

web前端-JS面试题总结



await

await只能放在async函数中,作用是让后面的执行语句或方法要等待当前await方法的结果后才能再执行。


 function doubleAfter2seconds(num) {

     return new Promise((resolve, reject) => {

         setTimeout(() => {

             resolve(2 * num)

         }, 2000);

     })

 }

 async function testResult() {

     let first = await doubleAfter2seconds(30);

     let second = await doubleAfter2seconds(50);

     let third = await doubleAfter2seconds(30);

     console.log(first + second + third);

 }


 testResult()


6s后输出220

web前端-JS面试题总结


总结

async和await基本是组合使用的,async用来声明一个异步方法,返回的是一个promise对象,如果要获取到对应的返回值,就需要使用.then方法;


ES6的类

定义类

通过class关键字以及constructor函数来定义类


 class People {

     constructor(name, age) {

         this.name = name;

         this.age = age

     }

     say() {

         console.log('我叫' + this.name + '今年' + this.age);

     }

 }


 var p1 = new People('张三', 18)

 console.log(p1);

 p1.say()

web前端-JS面试题总结



静态方法

如Array.isArray()和Object.freeze()这种构造函数调用的方法称为:静态方法


  class People {

      constructor(name, age) {

          this.name = name;

          this.age = age

      }

      say() {

          console.log('我叫' + this.name + '今年' + this.age);

      }


      // 这个就是静态函数

      static k() {

          console.log('我是静态函数');

      }

  }


  var p1 = new People('张三', 18)

  console.log(p1);

  p1.say()

  // 调用静态函数

  People.k()

web前端-JS面试题总结


es6类的继承(上面有es5的继承方法记得回去看看)

通过extends和super来继承父类的属性和方法


 class people {

     constructor(name, age) {

         this.name = name;

         this.age = age

     }

     say() {

         console.log('我叫' + this.name + '今年' + this.age);

     }


     // 这个就是静态函数

     static k() {

         console.log('我是静态函数');

     }

 }


 var p1 = new people('张三', 18)

 console.log(p1);

 p1.say()

 // 调用静态函数

 people.k()


 console.log('---------------------分割线-------------------------');


 class Coder extends people {

     constructor(name, age, job) {

         // 继承父元素的属性

         super(name, age)

         this.job = job

     }

     coding() {

         console.log(this.name + '爱敲代码');

     }

 }


 var c1 = new Coder('李四', 35, '前端工程师')

 console.log(c1);

 c1.say()

 c1.coding()

 Coder.k()

web前端-JS面试题总结



for of只可以用在数组,for in在数组和对象上都可以

深拷贝与浅拷贝以及实现的方法

map和weakMap的区别(Map)

Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

WeakMap 结构与 Map 结构类似,也是用于生成键值对的集合。但是 WeakMap 只接受对象作为键名( null 除外),不接受其他类型的值作为键名。而且 WeakMap 的键名所指向的对象,不计入垃圾回收机制。

JavaScript脚本延迟加载的方式有哪些

defer 属性: 给 js 脚本添加 defer 属性,这个属性会让脚本的加载与文档的解析同步解析,然后在文档解析完成后再执行这个脚本文件,这样的话就能使页面的渲染不被阻塞。多个设置了 defer 属性的脚本按规范来说最后是顺序执行的,但是在一些浏览器中可能不是这样。

async 属性: 给 js 脚本添加 async 属性,这个属性会使脚本异步加载,不会阻塞页面的解析过程,但是当脚本加载完成后立即执行 js 脚本,这个时候如果文档没有解析完成的话同样会阻塞。多个 async 属性的脚本的执行顺序是不可预测的,一般不会按照代码的顺序依次执行。

动态创建 DOM 方式: 动态创建 DOM 标签的方式,可以对文档的加载事件进行监听,当文档加载完成后再动态的创建 script 标签来引入 js 脚本。

使用 setTimeout 延迟方法: 设置一个定时器来延迟加载js脚本文件

让 JS 最后加载: 将 js 脚本放在文档的底部,来使 js 脚本尽可能的在最后来加载执行。

数组的原生方法

数组和字符串的转换方法:toString()、toLocalString()、join() 其中 join() 方法可以指定转换为字符串时的分隔符。

数组尾部操作的方法 pop() 和 push(),push 方法可以传入多个参数。

数组首部操作的方法 shift() 和 unshift() 重排序的方法 reverse() 和 sort(),sort() 方法可以传入一个函数来进行比较,传入前后两个值,如果返回值为正数,则交换两个参数的位置。

--------------------------------------上面的方法会改变原数组 -----------------------------------------------


数组连接的方法 concat() ,返回的是拼接好的数组,不影响原数组。

数组截取办法 slice(),用于截取数组中的一部分返回,不影响原数组。

数组插入方法 splice(),影响原数组查找特定项的索引的方法,indexOf() 和 lastIndexOf() 迭代方法 every()、some()、filter()、map() 和 forEach() 方法

数组归并方法 reduce() 和 reduceRight() 方法


✅  扫码免费获取IT基础课程 · IT技术干货 · 答疑解惑 · 职业测评

web前端-JS面试题总结

本文由 @小职 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    ICP许可  沪B2-20190160

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程