• 前端现场笔试题


    现场面试题

    沛华给的学生的笔试题

    1. css3 新增的伪类元素有哪些?

      • :before
      • :after
      • :first-child
      • :first-of-type
      • :last-child
      • :nth-of-type
    2. 伪类选择器有哪些?link、visited、hover、active

    3. 单行文本溢出以省略号表示:

      width:多少px自己决定;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      注:ellipsis :  当对象内文本溢出时显示省略标记
      助记:WTO
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    4. 多行文本溢出以省略号表示:

      overflow: hidden;
      text-overflow: ellipsis;
      display: -webkit-box;
      -webkit-line-clamp: 2;    // 最大行数
      -webkit-box-orient: vertical;
      
      • 1
      • 2
      • 3
      • 4
      • 5
    5. 移动端适配方案 flexible.js 的实现原理大概是怎样的?

      作用:它就是一个终端设备适配的解决方案。也就是说它可以让你在不同的终端设备中实现页面适配。

      使用:flexible.js 的用法非常的简单,在页面的中引入 flexible_css.js,flexible.js文件。

      flexible做的三件事:

      • 动态改写标签
      • 给元素添加data-dpr属性,并且动态改写data-dpr的值
      • 给元素添加font-size属性,并且动态改写font-size的值

      博客链接

    6. 遍历数组的方式有几种?哪种方式能中途停止?

      map、filter、forEach、some(能中途停止)、every、reduce

      博客链接

    7. js 如何判断一个变量是否为数组?

      1. instanceof

        let arr = [1, 2, 3]
        let res = arr instanceof Array
        console.log(res)
        
        • 1
        • 2
        • 3
      2. 数组方法:isArray()

        let arr = [1, 2, 3]
        let res = Array.isArray(arr)
        console.log(res)
        
        • 1
        • 2
        • 3
      3. 原型prototype + toString + call()

        let arr = [1, 2, 3]
        let res = Object.prototype.toString.call(arr).slice(8, -1).toLowerCase()
        console.log(res)
        
        • 1
        • 2
        • 3
      4. 原型prototype + isPrototypeOf()

        注:isPrototypeOf() 是 Object函数(类)的下的一个方法,用于判断当前对象是否为另外一个对象的原型,如果是就返回 true,否则就返回 false

        let arr = [1, 2, 3]
        let res = Object.prototype.isPrototypeOf(arr)
        console.log(res) // true
        
        • 1
        • 2
        • 3
      5. 构造函数 constructor

        let arr = [1, 2, 3]
        let res = arr.constructor
        console.log(res) // Array() { [native code] }
        
        • 1
        • 2
        • 3

      博客链接

    8. js 把 Object 的实例化对象 A、B、C 合并,赋值给对象 C。

      方法一:

      let c = Object.assign(A, B, C)

      方法二:

      let a = [1, 2, 3]
      let b = [4, 5, 6]
      let c = [...a, ...b]
      console.log(c)
      
      • 1
      • 2
      • 3
      • 4
    9. const Greeters = [];
      for (var i = 0; i < 10; i++) {
        Greeters.push(function() {
          return console.log(i)
        })
      }
      Greeters[0]() // 10
      Greeters[1]() // 10
      Greeters[2]() // 10
      // 注意:在for循环中它用的是 var 关键字,所以得到的结果是一样的。
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      const Greeters = [];
      for (let i = 0; i < 10; i++) {
        Greeters.push(function() {
          return console.log(i)
        })
      }
      Greeters[0]() // 0
      Greeters[1]() // 1
      Greeters[2]() // 2
      // 这里用的是 let 关键字
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
    10. var name = 'world!';
      (function() {
        if(typeof name === 'undefined') {
          var name = 'Jack';
          console.log("Goodbye" + name);
        } else {
          console.log('Hello' + name);
        }
      })() // GoodbyeJack
      
      // 注意:console.log(typeof name === 'undefined'); 为 true。意思就是说有没有 var name = 'world!'; 结果都是 GoodbyeJack。
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    11. const num = {
        a: 10,
        add() {
          return this.a +2
        },
        reduce: () => this.a - 2
      };
      console.log(num.add()); // 12
      console.log(num.reduce()); // NaN
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    12. 谈谈小程序的双向绑定和 Vue 的异同?(小程序里面的双向绑定和 vue 中的双向绑定有什么区别?)

      小程序的数据双向绑定:

      • 首先通过 bindinput 绑定文本框的输入事件。
      • 在 data 中声明一个变量 content ,将其动态绑定成文本框的 value 值。
      • 在 bindinput 事件中通过事件参数 e.detail.value 可以获取到文本框中最新的 value 值。
      • 通过 this.setData 将文本框最新的 value 值 赋值给 动态绑定的 value 值 content 即可实现数据的双向绑定。

      vue 的数据双向绑定:

      • 首先为文本框绑定 @input 监听文本框的输入事件。
      • 为文本框动态绑定 value 属性,其值是在 data 中定义的变量。
      • 在 @input 绑定的事件中 通过事件参数 event.target.value 可以获取到 input 框中最新的 value 值。
      • 将其重新获取到的 value 赋值给 value 值动态绑定的那个变量。

      区别:

      • 大体上区别不大,绑定事件不同,以及获取 value 值的具体方式不同,以及在小程序中设置 data中的数据,需要调用 this.setData 方法进行设置。
    13. uniApp 开发中如何获取上一个页面传递的数据?(uniapp 中获取上一页内容)

      let pages = getCurrentPages();
      let page = pages[pages.length - 2];
      page.$vm.refreshflag = true;(此参数为上一页中的参数)
      
      • 1
      • 2
      • 3
    14. 写出以下的输出结果:

      console.log('1' + 2 + 3); // "123"
      console.log('' == false); // true
      console.log(0 == false); // true
      console.log(undefined == false); // false
      console.log(1 + 2 + '3'); // "33" // 引起注意
      console.log('0' == false); // true
      console.log('0' === false); // false
      console.log('123' == false); // false
      console.log(-1 == false); // false
      console.log(-1 == true); // false
      console.log(!!undefined == false); // true
      console.log(typeof a); // undefined
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    15. function count() {
        var arr = [];
        for (var i = 1; i <= 3; i++) {
          arr.push(function () {
            return i * i
          })
        }
        return arr;
      }
      
      var results = count();
      var f1 = results[0];
      var f2 = results[1];
      var f3 = results[2];
      
      console.log(f1()); // 16
      console.log(f2()); // 16
      console.log(f3()); // 16
      // 原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了4,因此最终结果为16。(即,返回函数是在循环函数结束后才开始执行)
      
      // 返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
    16. 写出排序结果:

      var a = ['Google','Apple','Microsoft'].sort();
      var b = ['Google','apple','Microsoft'].sort();
      var c = ['Google','zpple','Microsoft'].sort();
      var d = [10, 20, 1, 2].sort();
      
      console.log(a); // [ 'Apple', 'Google', 'Microsoft' ]
      console.log(b); // [ 'Google', 'Microsoft', 'apple' ]
      console.log(c); // [ 'Google', 'Microsoft', 'zpple' ]
      console.log(d); // [ 1, 10, 2, 20 ]
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    17. 请结合你对 vue 生命周期的理解分别写出 this.message 与 this.$el 的打印结果:

      let vm = new Vue({
        el: "app",
        data: {
          message: 1
        },
        template:'

      {{message}}

      '
      , created() { console.log('调用了created'); // 第二步:'调用了created' console.log(this.message); // 1 console.log(this.$el); // undefined }, beforeMount() { console.log('调用了beforeMount'); // 第三步 '调用了beforeMount' console.log(this.message); // 1 console.log(this.$el); //
    }, beforeCreate() { console.log('调用了beforeCreate'); // 第一步: '调用了beforeCreate' console.log(this.message); // undefined console.log(this.$el); // undefined }, mounted() { console.log('调用了mounted'); // 第四步: '调用了mounted' console.log(this.message); // 1 console.log(this.$el); //

    {{message}}

    }, }) vm.message = 2;
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
  • 什么时候输出 1:

    setTimeout(function() {
      console.log(1);
    },2000)
    
    var time = Date.now();
    while(Date.now() - time < 5000){};
    // 5秒以后输出1。定时器里面的回调是异步的,等同步的 while 循环执行完之后才会执行。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • let a = {
      n:1
    };
    
    let b = a;
    
    a.x = a = {
      n:2
    };
    
    console.log(a.x); // undefined
    console.log(b.x); // {n: 2}
    // 难度在a.x
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • JS 合并两个数组的方法:

    var a = [1, 2, 3];
    var b = [4, 5, 6];
    // 1. concat
    var c = a.concat(b); // c = [1, 2, 3, 4, 5, 6];
    
    // 2. for 循环
    for (var i in b) {
        a.push(b[i]);
    }
    
    // 3. apply
    a.push.apply(a,[4, 5, 6]);
    
    // 4. 扩展运算符
    var c = [...a, ...b]
    console.log(c); // c = [1, 2, 3, 4, 5, 6];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • (function executionSequence() {
      setTimeout(function() {
        console.log(1);
      },0)
      new Promise(function(resolve,reject){
        console.log(2);
        resolve()
        console.log(3)
      }).then(function() {
        console.log(4)
      })
      console.log(5)
    })() // 2 3 5 4 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • js DOM 操作方法:

    • write():这个方法可以把任意字符串插入到文档中。
    • createElement():创建一个元素节点。
    • appendChild():将新节点追加到子节点列表的末尾。
    • createTextNode():创建一个文本节点。
    • insertBefore():将新节点插入在前面。
    • replaceChild():将新节点替换旧节点。
    • cloneNode():复制节点。
    • removeChild():移除节点。
    • 查找节点:getElementById(),querySelector()等。
  • 1rem、1em、1vh、1px 各自代表的含义?

    **rem: **页面所有使用 rem 单位的长度都是相对于根元素元素的 font-size 大小。即 1rem 等于根元素元素的 font-size 大小。

    em:

    • 子元素字体大小的 em 相对于父元素字体的大小。
    • 元素的 width/height/padding/margin 用 em 的话是相对于该元素的 font-size。

    **vh、vw:**全称是 Viewport Width 和 Viewport Height,视口的宽度和高度,1vh 相当于 视口高度的 1%。

    **px:**px像素(Pixel),相对长度单位。像素px是相对于显示器屏幕分辨率而言的。

    一般电脑的分辨率有 {1920*1080} 等不同的分辨率。

    1920*1080 前者是屏幕宽度总共有 1920 个像素,后者则是高度为 1080 个像素。

  • 如何中断 Ajax 请求?

    有两种方式:

    1. 设置超时时间让 Ajax 自动断开。
    2. 手动去停止 Ajax 请求,核心是调用 XMLHttpRequest 对象上的 abort 方法。
    xmlHttp.open("POST","Url",true);
    xmlHttp.onreadystatechange=function(){
    	...// 得到响应之后的操作
    }
    xmlHttp.send();
    // 设置3秒钟后检查xmlHttp对象所发送的数据是否得到响应.
    setTimeout("CheckRequest()","3000");
      function CheckRequest(){
      //为4时代表请求完成了
      if(xmlHttp.readyState!=4){
        alert('数据响应超时');
        //关闭请求
        xmlHttp.close();
      }
    }<br>//根据响应状态的改变关闭
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    **切记:**不可用 abort 方法来作为终止对服务器的请求操作,只有当做在前端页面立刻停止执行 ajax 成功后的方法,因为你执行 abort 方法后,ajax 很可能已经对服务端发送了请求,只是还未返回回馈信息而已。

  • Vuex 中的 action 和 mutation 的区别:

    • 流程顺序:视图触发 Action,Action 再触发 mutation。

    • 角色定位:

      Action:业务代码、异步请求。

      Mutation:专注于修改 State,理论上是修改 State 的唯一途径。

    • 限制:

      Mutation:必须同步执行。(Mutation 中采取异步函数仍然是有效的,可以实现对 state 状态的更改,但是不推荐)

      Action:可以异步,但不能直接操作 State。

  • 小程序, uni-app 生命周期:

    1. onLoad:首次进入页面加载时触发,可以在 onLoad 的参数中获取打开当前页面路径中的参数。
    2. onShow:加载完成后、后台切到前台或重新进入页面时触发。
    3. onReady:页面首次渲染完成时触发。
    4. onHide:从前台切到后台或进入其他页面触发。
    5. onUnload:页面卸载时触发。
    6. onPullDownRefresh:监听用户下拉动作。
    7. onReachBottom:页面上拉触底事件的处理函数。
    8. onShareAppMessage:用户点击右上角转发。
  • 为什么要用闭包?

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

  • js 实现数组的随机排序。

    方法一:通过数组中的 sort 方法实现,return 一个 Math.random()-0.5

    var arr = [1,2,3,4,5,6,7,8,9,10];
    arr.sort(function(){
        return Math.random() - 0.5;
    })
    console.log(arr);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    方法二:遍历当前数组,并创建一个暂存容器,每次遍历时,出现一个随机索引,使用随机索引,获取数组中一个随机的值,取出到暂存容器,然后根据当前循环次数的索引,获取数组中的值,放入原来取出的地方,最后把暂存容器的值,赋值给当前循环次数的索引的值,实现随机排序;(即三个容器间的交互)

    var arr = [1,2,3,4,5,6,7,8,9,10];
    function randSort1(arr){
      for(var i = 0,len = arr.length;i < len; i++ ){
            var rand = parseInt(Math.random()*len);
            var temp = arr[rand];
            arr[rand] = arr[i];
            arr[i] = temp; 
       }
       return arr;
    } 
    console.log(randSort1(arr));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 介绍一下 Web Storage 的概念和用法。

    Web Storage 包含如下两种机制:

    • sessionStorage 为每一个给定的源(given origin)维持一个独立的存储区域,该存储区域在页面会话期间可用(即只要浏览器处于打开状态,包括页面重新加载和恢复)。
    • localStorage 同样的功能,但是在浏览器关闭,然后重新打开后数据仍然存在。

    这两种机制是通过 Window.sessionStorage 和 Window.localStorage 属性使用(更确切的说,在支持的浏览器中 Window 对象实现了 WindowLocalStorage 和 WindowSessionStorage 对象并挂在其 localStorage 和 sessionStorage 属性下)—— 调用其中任一对象会创建 Storage 对象,通过 Storage 对象,可以设置、获取和移除数据项。对于每个源(origin)sessionStorage 和 localStorage 使用不同的 Storage 对象——独立运行和控制。

  • // promise中的.then方法是微任务,定时器是宏任务
    setTimeout(function(){
     console.log('定时器开始啦');
    });
    new Promise (function(resolve) {
     console.log('马上执行 for 循环');
     for(var i = 0; i < 10000; i++) {
       i == 99 && resolve();
     }
    }).then(function() {
     console.log('执行 then 函数');
    });
    console.log('代码执行结束');
    // 1. '马上执行 for 循环'
    // 2. '代码执行结束'
    // 3. '执行 then 函数'
    // 4. '定时器开始啦'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • var name = "The Window";
    var object = {
     name: "My Object",
     getNameFunc: function () {
       return function () {
         return this.name
       }
     }
    }
    console.log(object.getNameFunc()()); // ‘The Window’
    // 解析:
    // 1. object.getNameFunc() 得到的是一个return出来的一个函数。
    // 2. object.getNameFunc()() 把return出来的函数调用,这个就属于隐式类型转换(光秃秃的调用), this指向window
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • var name = "The Window";
    var object = {
     name: "My Object",
     getNameFunc: function () {
       var that = this;
       return function () {
         return that.name
       }
     }
    }
    console.log(object.getNameFunc()()); // My Object
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 前端路由和后端路由的区别?

    • 什么是路由?

    路由是根据不同的 URL 展示不同的内容和页面。

    • 什么是前端路由?

      **特点:**不向后台发送请求,不刷新页面,前后端分离。

      前端路由即响应页面内容的任务是由前端来做的,根据不同的 url 更新页面的内容,随着 SPA(单页面应用)的普遍使用,前后端开发分离,项目中基本都使用前端路由,通过路由实现页面的变化。例如,通过 vue 开发的 SPA 中,切换路由,并不刷新页面,而是根据路由在虚拟 DOM 中加载所需要的数据,实现页面内容的改变。

    • 什么是后端路由?

      **特点:**向服务器发送请求,会刷新页面,前后端分离。

      在浏览器的地址栏中切换不同的 url 时,每次都向后台服务器发出请求,服务器根据不同的响应不同的数据,浏览器接收到数据后再进行渲染,所以后端路由会刷新页面,如果网速慢的话,就会看到一个空白页面等待服务端返回数据,后台路由最大的问题就是不能前后端分离。

    • 什么时候使用前端路由?

      在单页面应用中,大部分页面结构不变,只改变部分内容时使用。

    • 前端路由的优缺点:

      优点:

      • 用户体验好,页面初始化后,只需要根据路由变换页面内容,不需要再向服务器发送请求,内容变换速度快。
      • 可以在浏览器中输入指定想要访问的 url。
      • 实现了前后端分离,方便开发。

      缺点:

      • 使用浏览器的前进、后退键的时候会重新发送请求,没有合理的利用缓存。
      • 单页面无法记住之前滚动的位置,无法在前进、后退的时候记住滚动的位置。
  • node.js 中如何读写文件?

    nodejs 中所有与文件相关的操作都在fs模块中,而读写操作又是我们会经常用到的操作,nodejs 的 fs 模块针对读操作为我们提供了readFile,read, createReadStream 三个方法,针对写操作为我们提供了writeFile,write, createWriteStream 三个方法。

    博客地址

  • Linux 中常用的命令?(沛华博客)

    Linux是一套开源免费的操作系统,与系统的交互通常用命令来实现,常用的命令有:

    • ls 查看当前文件夹下的文件(list单词的缩写), ls -al or ls -a -l查看隐藏文件并竖向排列
    • cd 进入某一个文件夹(change directory)的缩写,cd ..回到上一级。tab键代码自动补全
    • clear 清屏
    • mkdir 创建文件夹
    • touch test.html 创建一个文件
    • rm test.html 删除一个文件
    • rm -r dir 删除文件夹
    • mv 原文件或文件夹 目标文件或文件夹 移动文件
    • cat test.html 查看文件内容
    • ctrl+c 取消命令
  • 使用 CSS 实现一个三角形。

    DOCTYPE html>
    <html lang="en">
        <head>
            <meta name="keywords" content="zidingyi">
            <meta name="description" content="zidingyi">
            <meta>
            <title>triangletitle>
            <style>
                div {
                    height: 0;
                    width: 0;
                    border: 100px solid transparent;
                    border-bottom: 100px solid red;
                }
            style>
        head>
        <body>
            <div>div>
        body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
  • 若干根粗细不均匀的绳子,每根烧完均需要1小时,怎样烧能计时45分钟?

    30 分钟:把一根绳子从两头同时烧, 就能得到30分钟了。
    45 分钟:方法类似。其中一根绳子从两头烧得到30分钟,另外一根绳子从中折一下两头一起烧,两段时间加起来就可以了。

  • 假如每3个空啤酒瓶可以换一瓶啤酒,某人买了 10 瓶啤酒,那么他最多可以喝到多少瓶?

    喝完10瓶后用9个空瓶换来3瓶啤酒(喝完后有4个空瓶) 喝完这三瓶又可以换到1瓶啤酒(喝完后有2个空瓶)
    这时他有2个空酒瓶,如果他能向老板先借一个空酒瓶,就凑够了3个空瓶可以换到一瓶啤酒,把这瓶喝完后将空瓶还给老板就可以了。
    所以他最多可以喝 10+3+1+1 = 15 瓶。

  • 小程序组件之间数据传递:博客地址

  • 小程序页面跳转和参数传递。

    跳转的三种方式:

    1. wx.navigateTo():保留当前页面,跳转到应用内的某个页面,使用 wx.navigateBack可以返回到原页面。
    2. wx.redirectTo():关闭当前页面,跳转到应用内的某个页面。
    3. 使用组件.

    wx.navigateTo() 和 wx.redirectTo() 的区别:

    • wx.navigateTo() 是保留当前页面,跳转到某个页面,跳转页面后可以返回上一页。
    • wx.redirectTo() 是关闭当前页面,跳转到某个页面,跳转页面后不能返回上一页。

    博客地址

  • 输出结果:

    emp = new Array(5);
    emp[1] = 1;
    emp[2] = 2;
    document.write(emp.length); // 5
    
    • 1
    • 2
    • 3
    • 4
  • 能够返回键盘上的按键对应字符的事件是:onkeypress事件。

  • 关于 document 对象的属性错误的是(B)

    A. body 是它的属性

    B. close 是它的属性(这个不属于,可以通过console.dir(document)检查)

    C. title 是它的属性

    D. bgColor 是它的属性

  • 退出 用于关闭浏览器窗口。

  • 请输出结果:

    var a = 1;
    if (true) {
      console.log(a); // 报错,因为let不会变量提升。
      let a = 2;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • var a = {n:1};
    var b = a;
    
    a.x = a = {n:2};
    console.log(a.n,b.n); // 2 1
    console.log(a.x,b.x); // undefine {n:2}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 谈谈你对 HTTP 协议的理解:(来自http课件)

    协议是指计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则。

    HTTP(hypertext transport protocol)协议也叫超文本传输协议,是一种基于 TCP/IP 的应用层通信协议,这个协议详细规定了浏览器和万维网服务器之间互相通信的规则。

    客户端与服务端通信时传输的内容我们称之为报文。

    HTTP 就是一个通信规则,这个规则规定了客户端发送给服务器的报文格式,也规定了服务器发送给客户端的报文格式。实际我们要学习的就是这两种报文。客户端发送给服务器的称为“请求报文”,服务器发送给客户端的称为“响应报文”。

  • 项目中如何修改 UI 框架的样式?

    1. 行内修改样式:通过在行内设置 style 修改,用于局部组件块。

    2. scoped 问题:可以去掉 scoped。

    3. vue2 deep 样式穿透方法:在不去掉 scoped 的情况下,我们可以用 /deep/ 或使用 >>> 来更改样式。

    4. vue3 deep 样式穿透方法:在不去掉 scoped 的情况下,我们可以用 :deep() 或使用 ::v-deep 来更改样式。

      ::v-deep .el-form-item {
        border: 1px solid rgba(255, 255, 255, 0.1);
        background: rgba(0, 0, 0, 0.1);
        border-radius: 5px;
        color: #454545;
      }
      
      或者使用
      :deep(.el-form-item) {
        border: 1px solid rgba(255, 255, 255, 0.1);
        background: rgba(0, 0, 0, 0.1);
        border-radius: 5px;
        color: #454545;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14

      博客地址

  • 找出字符串中第一个只出现一次的字母

    var str = 'eerratrefffp'
    function fun(str){
        var arr = [],arr1 = []
        arr = str.split('')
        arr.forEach(function(item,index){
            var num  = str.split(item).length - 1
            if(num == 1){
                arr1.push(item)
            }
        })
        if(!arr1.length == 0){
            console.log(arr1[0])
        }else{
            console.log('没有符合条件的值')
        }
    }
    fun(str) // a
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    博客地址

  • 输出结果:

    // 1
    var strA = "hi there";
    var strB = strA;
    strB = "bye there";
    console.log(strA);
    console.log(strB);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    折叠代码块1 console.log(strA); // hi there console.log(strB); // bye there
    // 2
    var objA = {prop1: 42};
    var objB = objA;
    objB = {};
    console.log(objA); 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    折叠代码块2 // {prop1: 42}
    // 3
    var arrA = [0, 1, 2, 3, 4, 5];
    var arrB = arrA;
    arrB[0] = 42; // 同一个地址值
    console.log(arrA); 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    折叠代码块3 // [42, 1, 2, 3, 4, 5]
    // 4
    var employeeId = 'abc123';
    function foo() {
      employeeId = '123abc';
      return;
    }
    foo();
    console.log(employeeId); 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    折叠代码块4 // '123abc'
    // 5
    function foo() {
      employeeId();
      var product = 'Car';
      return;
      function employeeId() {
        console.log(product);
      }
    }
    foo(); 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    折叠代码块5 // undefined
    // 6
    var obj = {
      message: "Hello",
      innerMessage: !(function () {
        console.log(this.message)
      })()
    };
    console.log(obj.innerMessage);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    折叠代码块6 // undefined true // 因为在匿名函数自调用中的this指向的是window
    // 7
    function myFunc() {
      console.log(this.message);
    }
    myFunc.message = "Hi John";
    console.log(myFunc());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    折叠代码块7 // undefined undefined
    // 8
    function myFunc(param1,param2) {
      console.log(myFunc.length); 
    }
    console.log(myFunc());
    console.log(myFunc("a","b"));
    console.log(myFunc("a","b","c","d"));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    折叠代码块8 // 三个答案相同:undefined,函数没有return
    // 9
    (function() {
      var greet = "Hello World";
      var toGreet = [].filter.call(greet, function(element, index) {
        return index > 5;
      });
      console.log(toGreet);
    })();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    折叠代码块9 // [ 'W', 'o', 'r', 'l', 'd' ] 这个题目我看不懂:2022年8月31日14:26:54
    // 10
    function getDataFromServer(apiUrl) {
      var name = "John";
      return {
        then: function (fn) {
          fn(name);
        }
      }
    }
    
    getDataFromServer('www.google.com').then(function(name){
      console.log(name);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    折叠代码块10 // "John"
    // 11
    function mul (x) {
      return function (y) {
        return [x*y, function (z) {
          return x*y + z;
        }];
      }
    }
    console.log(mul(2)(3)[0]);
    console.log(mul(2)(3)[1](4));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    折叠代码块11 // 6 10
    // 12
    var a = 10;
    a.pro = 10;
    console.log(a.pro); 
    console.log(a.pro+a);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    折叠代码块12 console.log(a.pro); // undefined console.log(a.pro+a) // NaN(相当有undefined+a=NaN)
    // 13
    var s = 'hello';
    s.pro = 'world';
    console.log(s.pro+s);
    
    • 1
    • 2
    • 3
    • 4
    折叠代码块13 // 'undefinedhello'
  • 合并对象:合并 obj1, obj2, obj3,使用新变量obj4保存。

    // ES6在Object新加的方法  assign() 
    // 作用:将多个对象{}  合并成一个独立对象。
    // 使用方式: Object.assign(合并的对象,传入合并中的对象....)
    var obj1 = {name: 'xiaoming', age: 8, weight: '60kg'};
    var obj2 = {account: 'admin', password: 'admin'}
    var obj3 = {remember: true};
    
    var obj4 = Object.assign(obj1, obj2, obj3);
    console.log(obj4);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    // 使用ES6中的扩展运算符
    var obj1 = { name: 'xiaoming', age: 8, weight: '60kg' }
    var obj2 = { account: 'admin', password: 'admin' }
    var obj3 = { remember: true }
    
    // var obj4 = Object.assign(obj1, obj2, obj3)
    var obj4 = { ...obj1, ...obj2, ...obj3 }
    console.log(obj4)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 过滤对象中数据。

    /**
    * [过滤对象]
    * @param  obj [过滤前数据]
    * @param  arr [过滤条件,要求为数组]
    */
    function filterObj(obj, arr) {
        if (typeof (obj) !== "object" || !Array.isArray(arr)) {
        	throw new Error("参数格式不正确")
        }
    	const result = {}
    	Object.keys(obj).filter((key) => arr.includes(key)).forEach((key) => {
    		result[key] = obj[key]
    	})
    	return result
    }
    
    // 使用
    let obj = {
      a: '1',
      b: '2',
      c: '3'
    }
    
    let newObj = filterObj(obj,["a", "b"]);
    console.log(newObj);
    // 返回结果 :
    newObj = {
      a: '1',
      b: '2'
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
  • 怎么让 Chrome 支持小于 12px 的文字?

    <style>
        p span {
          font-size: 10px;
          -webkit-transform: scale(0.8);
          display: block;
        }
    style>
    <body>
      <p><span>haorooms博客测试10pxspan>p>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • const promise = new Promise ((resolve,reject) => {
      console.log(1);
      resolve();
      console.log(2)
    })
    promise.then(() => {
      console.log(3)
    })
    console.log(4); 
    // 1 2 4 3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • function Foo() {
      var i = 0;
      return function() {
        console.log(i++);
      }
    }
    var f1 = Foo(), f2 = Foo();
    f1();
    f1();
    f2();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    折叠代码块
    f1(); // 0
    f1(); // 1
    f2(); // 0
        
  • var a = "40";
    var b = 7;
    console.log(a % b);
    
    • 1
    • 2
    • 3
    折叠代码块
    // 5 (数字5)
        
  • 如果同时有两个请求,怎么让他们分开发送(一个请求结束,另一个请求开始)

    .then链式调用,或者使用async+await

    博客地址

  • 全屏滚动的原理是什么? 用到了css的那些属性?

    • 全屏滚动和轮播图类似,都是通过改变元素位置或者显示与隐藏来实现,配合JS的一些交互距离判断,实现类似原生滚动捕获的效果。
    • 关键CSS属性是父容器 overflow: hidden; 。
    • 实现全屏滚动还可以简单的通过插件来实现,比如fullpage,很多大公司的页面都是用这个实现的,比如小米一些产品的官网。

  • 1215面试题(笔试)

    1. 有哪些方法可以遍历对象中的所有属性?这些方法有何区别?

      • Object.keys()

        Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 。如果对象的键-值都不可枚举,那么将返回由键组成的数组。

      • Object.values() 返回属性值。

        **Object.values()**方法返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用for...in循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。

      • Object.entries()

      **Object.entries()**方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环也枚举原型链中的属性)。

      Object.entries() 返回键值对数组,如 [ [key1, value1], [key2, value2], ..., [keyN, valueN] ]

      博客链接

    2. for of 和 for in 的区别?

      • for of 无法遍历 不可迭代的对象。

        可迭代的对象包括:Array, Map, set, String, TypedArray, arguments等。

      • for of 遍历的是值,for in 遍历的是key。

    3. let arr = ['a', 'b', 'c', 'd', 'e']
      
      for (let i of arr) {
        console.log(i)
      }
      // 'a', 'b', 'c', 'd', 'e'
      
      
      for (let i in arr) {
        console.log(i)
      }
      // 0 1 2 3 4
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    4. 以下布尔转换的结果是什么?

      console.log(Boolean(0)); // false
      console.log(Boolean(1)); // true
      console.log(Boolean(NaN)); // false
      console.log(Boolean("  ")); // true
      console.log(Boolean("")); // false
      console.log(Boolean([])); // true
      console.log(Boolean({})); // true
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    5. 以下哪些情况会导致回流?哪些情况会导致重绘?

      **reflow(回流)**是指浏览器为了重新渲染部分或者全部的文档,重新计算文档中的元素的位置。

      回流可能导致整个 DOM 树的重新构造,是性能的一大杀手。

      以下操作会引起回流:

      1. 改变窗口大小
      2. font-size 大小变化
      3. 增加或者溢出样式表
      4. 内容变化(input 中输入文字)
      5. 激活 CSS 伪类(:hover)
      6. 操作 class 属性,新增或者减少
      7. js 操作 dom
      8. offset 相关属性计算
      9. 设置 style 的值

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

    6. 以下程序的执行结果是什么?

      let f = () => {
      	console.log(this);
      }
      let o = {
        f,
        g: {
          h: f
        }
      };
      o.f(); // window
      o.g.h(); // window
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    7. let log = console.log;
      let timeId = 0;
      let handleReadyState = () => {
        if (document.readyState === 'complete') {
          window.clearTimeout(timeId);
          log('complete');
        }
      };
      let loop = () => {
        timeId = window.setTimeout(() => {
          handleReadyState();
          loop();// 递归调用loop
        }, 0);
      };
      loop();
      // 一直输出‘complete’死循环
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
    8. div+css 布局较 table 布局有什么优点?

      1. 改版的时候更方便,只要改 css 文件。
      2. 页面加载速度更快、结构化清晰、页面显示简洁。
      3. 样式与结构相分离。
      4. 易于优化(SEO)搜索引擎更友好,排名更容易靠前。
      5. 实现一些复杂的布局更加容易。
    9. js 延迟加载的几种方式?

      1. defer 属性:HTML 4.01 为