• vue面试题(4)


    1.介绍下 Set、Map、WeakSet 和 WeakMap 的区别?

    Set
    成员唯一、无序且不重复
    [value, value],键值与键名是一致的(或者说只有键值,没有键名)
    可以遍历,方法有:add、delete、has
    WeakSet
    成员都是对象
    成员都是弱引用,可以被垃圾回收机制回收,可以用来保存DOM节点,不容易造成内存泄漏
    不能遍历,方法有add、delete、has
    Map
    本质上是键值对的集合,类似集合
    可以遍历,方法很多可以跟各种数据格式转换
    WeakMap
    只接受对象作为键名(null除外),不接受其他类型的值作为键名
    键名是弱引用,键值可以是任意的,键名所指向的对象可以被垃圾回收,此时键名是无效的
    不能遍历,方法有get、set、has、delete

    2.setTimeout、Promise、Async/Await 的区别

    主要是考察这三者在事件循环中的区别,事件循环中分为宏任务队列和微任务队列。
    其中settimeout的回调函数放到宏任务队列里,等到执行栈清空以后执行;
    promise.then里的回调函数会放到相应宏任务的微任务队列里,等宏任务里面的同步代码执行完再执行;
    async函数表示函数里面可能会有异步方法,await后面跟一个表达式,
    async方法执行时,遇到await会立即执行表达式,
    然后把表达式后面的代码放到微任务队列里,让出执行栈让同步代码先执行。

    练习 下面代码输出顺序

    async function async1() {
        console.log('async1 start');
        await async2();
        console.log('async1 end');
    }
    async function async2() {
        console.log('async2');
    }
    console.log('script start');
    setTimeout(function() {
        console.log('setTimeout');
    }, 0)
    async1();
    new Promise(function(resolve) {
        console.log('promise1');
        resolve();
    }).then(function() {
        console.log('promise2');
    });
    console.log('script end');
    
    
    

    答案 想一想为什么?

    /*
    script start
    async1 start
    async2
    promise1
    script end
    async1 end
    promise2
    setTimeout
    */

    3.JS 异步解决方案的发展历程以及优缺点。

    Promise
    优点:解决了同步的问题
    缺点:无法取消 Promise ,错误需要通过回调函数来捕获
    Async/await
    优点是:代码清晰,不用像 Promise 写一大堆 then 链,处理了回调地狱的问题
    缺点:await 将异步代码改造成同步代码,如果多个异步操作没有依赖性而使用 await 会导致性能上的降低。

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

    const promise = new Promise((resolve, reject) => {
      console.log(1)
      resolve()
      console.log(2)
    })
    
    promise.then(() => {
      console.log(3)
    })
    
    console.log(4)
    
    
    执行结果是:1243
    promise构造函数是同步执行的,then方法是异步执行的
    

    5.Vue 的响应式原理

    Vue 的响应式原理中 Object.defineProperty 有什么缺陷?为什么在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty?
    1 Object.defineProperty无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应;
    2 Object.defineProperty只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,
    还需要深度遍历。Proxy可以劫持整个对象,并返回一个新的对象。
    3 Proxy不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。

    6.练习题

    6.1

    如下:{1:222, 2:123, 5:888},请把数据处理为如下结构:
    [222, 123, null, null, 888, null, null, null, null, null, null, null]。
    
    let obj = {1:222, 2:123, 5:888}; 
    //创建一个长度为12的空数组 循环吧对应的值得到obj的值 否则为空
    Array.from({ length: 12 }).map((item,index)=>{
         return   obj[index+1] || null    
    })  
    

    6.2

    var a = 10;
    (function () {
        console.log(a)
        a = 5
        console.log(window.a)
        var a = 20;
        console.log(a)
    })()
    
    
    =========================================================
    在立即执行函数中,var a = 20; 语句定义了一个局部变量 a,由于js的变量声明提升机制,局部变量a的声明会被提升至立即执行函数的函数体最上方,
    且由于这样的提升并不包括赋值,因此第一条打印语句会打印undefined,最后一条语句会打印20。
    由于变量声明提升,a = 5; 这条语句执行时,局部的变量a已经声明,因此它产生的效果是对局部的变量a赋值,
    此时window.a 依旧是最开始赋值的10,
    

    6.3下面代码中 a 在什么情况下会打印 1?

    var a = ?;
    if(a == 1 && a == 2 && a == 3){
     	console.log(1);
    }
    

    6.3答案

    var a = {
      a: 1,
      toString() {
        return ++this.a;
      }
    }
    
    if( a == 1 && a == 2 && a == 3 ) {
      console.log(1);
    }
    ===================================
    let a = [1,2,3];
    a.toString = a.shift;
    if( a == 1 && a == 2 && a == 3 ) {
      console.log(1);
    }
    

    6.4简单改造下面的代码,使之分别打印 10 和 20。

    var b = 10;
    (function b(){
        b = 20;
        console.log(b); 
    })();
    

    6.4答案

    打印10
    var b = 10;
    (function b(b) {
     window.b = 20;
     console.log(b)
    })(b)
    打印20
    var b = 10;
    (function b() {
     var b = 20;
     console.log(b)
    })()
    ==========
      var b = 10;
    (function b(b) {
     b = 20;
     console.log(b)
    })(b)
    

    6.5改造下面的代码,使之输出0 - 9,写出你能想到的所有解法

    for (var i = 0; i< 10; i++){
    	setTimeout(() => {
    		console.log(i);
        }, 1000)
    }
    
    
    
    ========================================================================================
    //方法1
    for (var i = 0; i< 10; i++){
       setTimeout((i) => {
       console.log(i);
       }, 1000,i)
    }
    //方法2
    for (let i = 0; i< 10; i++){
      setTimeout(() => {
        console.log(i);
      }, 1000)
    }
    

    6.6全局作用域中,用 const 和 let 声明的变量不在 window 上,那到底在哪里?如何去获取?

    用 let 和 const 声明的全局变量并没有在全局对象中,只是一个块级作用域(Script)中

    怎么获取?在定义变量的块级作用域中就能获取啊,既然不属于顶层对象,那就不加 window(global)呗。
    let aa = 1;
    const bb = 2;

    console.log(aa); // 1
    console.log(bb); // 2

    6.7['1', '2', '3'].map(parseInt) what & why ?

    而parseInt则是用来解析字符串的,使字符串成为指定基数的整数。
    parseInt(string, radix)
    parseInt('1', 0) //radix为0时,且string参数不以“0x”和“0”开头时,按照10为基数处理。这个时候返回1
    parseInt('2', 1) //基数为1(1进制)表示的数中,最大值小于2,所以无法解析,返回NaN
    parseInt('3', 2) //基数为2(2进制)表示的数中,最大值小于3,所以无法解析,返回NaN

    练习 ['10','10','10','10','10'].map(parseInt);

    // 10 nan 2 3 4

  • 相关阅读:
    不要为自己找借口,你可以做到的--职场实用做人法则
    sql server 利用发布订阅方式实现数据库同步问题
    关于免费空间的寻找
    数据自定义格式化
    C++字符串string类常用操作详解(一)【初始化、遍历、连接】
    C++ 命名空间
    gcc/g++ 如何支持c11 / c++11标准编译
    正确的C++/C堆栈
    linux下清空c++ cin无效流的方式
    32位64位下各种数据类型大小的对比
  • 原文地址:https://www.cnblogs.com/loveliang/p/13690929.html
Copyright © 2020-2023  润新知