JS面试题

//经典面试题
async function async1 () {
  console.log('async1 start') //2
  //await后面都是回调内容--微任务
  await async2() // 这一句会同步执行,返回 Promise ,其中的 `console.log('async2')` 也会同步执行
  console.log('async1 end') //6 上面有 await ,下面就变成了“异步”,类似 cakkback 的功能(微任务)
}

async function async2 () {
  console.log('async2')//3
}

console.log('script start')//1

setTimeout(function () { // 异步,宏任务
  console.log('setTimeout')//8
}, 0)

async1()

//初始化promise时,传入的函数会立刻被执行
new Promise (function (resolve) { // 返回 Promise 之后,即同步执行完成,then 是异步代码
  console.log('promise1') //4  Promise 的函数体会立刻执行 
  resolve()
}).then (function () { // 异步,微任务
  console.log('promise2')//7
})

console.log('script end')//5

// 同步代码执行完之后,屡一下现有的异步未执行的,按照顺序
// 1. async1 函数中 await 后面的内容 —— 微任务
// 2. setTimeout —— 宏任务
// 3. then —— 微任务
//除了宏任务和微任务其他都是同步的

从JS基础知识到JS Web API

  • JS基础知识,规定语法(ECMA 262标准)
  • JS Web API,网页操作的API(w3c标准)
  • 前者是后者的基础,两者结合才能真正实际应用

JS基础知识

  • 变量类型计算
  • 原型和原型链
  • 作用域和闭包

JS Web API

  • DOM
  • BOM
  • 事件绑定
  • ajax
  • 存储

前言

  • vue和React框架应用广泛,封装了DOM操作
  • 但是DOM操作一直都是前段工程师的基础,必备知识
  • 只会vue而不会DOM操作的前端程序员,不会长久

题目

  • DOM是那种数据结构
    • dom树
  • DOM操作常用的API
  • attr 和 property 的区别?
    • attr对dom结构的节点的属性修改,修改html属性,会改变html结构
    • property对js变量修改,修改对象属性值,不会体现到html中
    • property 和 attribute 都可能引起dom重新渲染,优选property
  • 一次性插入多个DOM节点,考虑性能
    • dom节点缓存
    • fragment

知识点

  • dom本质

    • 从html文件解析出来的树
  • dom节点操作

    • 获取dom节

    • attribute

      • 对dom结构的节点的属性修改,修改html属性,会改变html结 
    • property

      • 对js变量修改,修改对象属性,不会体现到html 
    • property 和 attribute 都可能引起dom重新渲染,优选property

9-3

  • dom结构操作

  • 新增/插入节

  • 获取子元素列表,获取父元素列表

    • 利用nodeType检查文本元素还是普通dom节点

    • 如果节点是一个元素节点,nodeType 属性返回 1。

    • 如果节点是属性节点, nodeType 属性返回 2。

    • 如果节点是一个文本节点,nodeType 属性返回 3。

      img
    • img
  • 删除子元素

  • dom性能

    • dom操作非常‘昂贵’,避免频繁的dom操作

    • 对dom查询做缓存

      • for循环中如果条件是需要对domlength进行计算,那就要把domlength计算写在for循环外边,定义一个新的变量保存,然后在for循环中使用这个自己定义的变量,可以避免因多次dom查询带来的性能消

    • 将频繁操作改为一次性操作

      • 如要创建多个新的dom挂到原有的dom节点上,可以先通过document.createDocumentFragment()创建一个文档片段,然后再把新创建的节点通过for循环和appendChild添加到文档片段上,最后将文档片段通过appendChild插入到最初指定的dom节点 

BOM操作

题目
  • 如何识别浏览器的类型
  • 分析拆解url各个部分

知识点:

  • navigator

    • userAgent: 属性是一个只读的字符串,声明了浏览器用于 HTTP 请求的用户代理头的值。
  • scree

  • location

  • histor

事件

题目

  • 编写一个通用的事件监听函数

  • 描述事件冒泡的流程

    • 基于dom树形结构
    • 事件会顺着触发元素往上冒泡
    • 应用场景:代理
  • 无限下拉的图片列表,如何监听每个图片的点击?

    • 事件代理

    • 用e.target获取触发元素

    • 用matches来判断是否触发元素

      <button id="btn1">一个按钮</button>
      
      <div id="div3">
        <a href="#">a1</a><br>
        <a href="#">a2</a><br>
        <a href="#">a3</a><br>
        <a href="#">a4</a><br>
      <button>加载更多...</button>
      </div>
      function bindEvent(elem, type, selector, fn) {
        console.log(selector);
        console.log(fn);
        if (fn == null) {
          fn = selector;
          selector = null
        }
        elem.addEventListener(type, event => {
          const target = event.target;
          console.log(target);
          if (selector) {
            // 代理绑定
            if (target.matches(selector)) {
              fn.call(target, event)
            }
          } else {
            // 普通绑定
            fn.call(target, event)
          }
        })
      }
      
      // 普通绑定
      const btn1 = document.getElementById('btn1')
      bindEvent(btn1, 'click', function (event) {
        // console.log(event.target) // 获取触发的元素
        event.preventDefault() // 阻止默认行为
        alert(this.innerHTML)
      })
      
      // 代理绑定
      const div3 = document.getElementById('div3')
      bindEvent(div3, 'click', 'a', function (event) {
        event.preventDefault()
        alert(this.innerHTML)
      })
      

知识点

  • 事件绑定

    //通用事件绑定函数
        function bindEvent(elem,type,fn){
            elem.addEventListener(type,fn);
        }
        const btn1 = document.getElementById('btn1');
        bindEvent(btn1,'click',event=>{
            event.preventDefault()
            alert('clicked')
        })
    
  • 事件冒泡

    <style>
    		#div1 {
    			width: 400px;
    			height: 400px;
    			background-color: red;
    		}
    
    		#div2 {
    			width: 100px;
    			height: 100px;
    			background-color: pink;
    		}
    	</style>
    </head>
    <body>
    <div id="div1">
    	div1
    	<div id="div2">div2</div>
    </div>
    <a href="http://www.baidu.com" id="baidu">百度</a>
    <script>
    	baidu.onclick = function (e) {
    		//window.event 兼容ie
    		let ev = window.event || e;
    		if (ev.preventDefault){
    			ev.preventDefault();
    		} else{
    			//兼容ie
    			ev.cancelValue = false;
    		}
    	};
    
    	div1.onclick = function () {
    		alert(1);
    	};
    	div2.onclick = function (e) {
    		alert(2);
    		let ev = window.event || e;
    		if (ev.stopPropagation) {
    			ev.stopPropagation();
    		} else {
    			//兼容ie
    			ev.cancelable;
    		}
    		//stopPropagation w3c标准浏览器
    		//ie 非w3c标准
    	}
    
    </script>