美文网首页
基础面试题js

基础面试题js

作者: 大萝蓓 | 来源:发表于2021-10-20 22:36 被阅读0次

    1、js的this是怎么工作的?(这个大概就是问this是什么)
    答:1、this总是指向函数的直接调用者。2、如果有new关键字,this指向new出来的那个对象。3、在MOD实践中,this指向目标元素。4、箭头函数的this指向它所在的函数作用域,并且不能改变,始终指向的是window。
    2、原型继承的原理?
    答:
    3、什么是闭包,怎么用?
    答:在js中函数可以访问函数外部的变量的,但是在外部拿不到内部的变量,A一个函数,B是A里面的子函数,在B里面把A的变量return出去,再把B函数给return出去,如果我要用A里面的变量就可以直接调用B函数了,这个就是闭包。
    优点:可访问函数内部的变量,防止变量污染作用域(隐藏变量),从而实现封装。
    缺点:本来局部变量会被垃圾回收机制给回收的,但是我们给返回到外面了,并且在引用的情况下,是不回被回收的,会造成内存的一些浪费
    4、call、apply、bind的区别是什么?
    答:call、apply、bind三个为改变this指向的方法。
    共同点:第一个参数都为改变this的指针。若第一参数为null/undefined,this默认指向window
    区别:call(无数个参数)参数是一个一个传递。第一个参数:改变this指向;第二个参数:实参;使用之后会自动执行该函数

    function fn(a,b,c){
            console.log(this,a+b+c); // this指向window
        }
        fn();
        fn.call(document,1,2,3);//call改变之后this指向document  
        //输出 #document 6   1,2,3是实参 结果相加为6
    

    apply(两个参数)是把所有参数组成一个数组传递。第一个参数:改变this指向;第二个参数:数组(里面为实参);使用时候会自动执行函数

    function fn(a,b,c){
            console.log(this,a+b+c); 
        }
        fn();
        fn.apply(document,[1,2,3]); 
    

    bind(无数个参数),第一个参数:改变this指向;第二个参数之后:实参;返回值为一个新的函数

    function fn(a,b,c){
        console.log(this,a+b+c); //window
    }
    let ff = fn.bind('小明',1,2,3); //手动调用一下
    

    使用的时候需要手动调用下返回 的新函数(不会自动执行)
    5、请指出js宿主对象(host object)和原生对象(native object)的区别?
    答:宿主对象是指DOM和BOM;宿主对象不是引擎的原生对象,是宿主框架通过某种机制注册到js引擎里的对象。
    原生对象是指Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、Math等对象。除了内置对象,还有一些在运行过程中创建出的对象。
    6、请指出下面代码的区别:function person()、var person = Parson()、var person = new Person()。
    答:function person():声明一个person函数,this指向window;var person = Parson():将Parson方法返回的结果给person变量,如果没有返回值则是undefined,this指向person;var person = new Person():创建一个构造函数,this指向Person。
    7、请解释变量声明提升
    答:举一个例子:

    foo(2);
    
    function foo(a){
      console.log(a);
    }
    

    编译阶段:1、先遇见了foo(2),一个函数执行,不是我编译器的活,略过。2、发现了function,告诉JS引擎编译器有函数要声明,需要在当前作用域内的内存中开辟一块空间给foo,继续编译函数内部(从上到下一行一行编译),遇到形参a后在函数内存里开辟一块空间给a,只不过现在a的值为undefined,继续走,结束。
    执行阶段:1、遇到了foo(2),引擎:作用域,你见过foo没?作用域:见过,刚才编译器那小子刚声明了他,我给你。引擎:好的。那我来执行以下foo这个函数。作用域兄弟,你在foo中见过a吗?作用域:有,编译器也声明他了,给你。引擎:谢了哥们,我把2复制给他。
    来一个测试题

    var a = new Object();
    a.param = 123;
    
    function foo(){
      get = function(){
          console.log(1);
      };
      return this;
    }
    
    foo.get = function(){
      console.log(2);
    };
    
    foo.prototype.get = function(){
      console.log(3);
    };
    
    var get = function(){
      console.log(4);
    };
    
    function get(){
      console.log(5);
    }
    
    foo.get();
    get();
    foo().get();
    get();
    new foo.get();
    new foo().get();
    new new foo().get();
    // 2,4,1,1,2,3,3
    

    8、什么是use strict?使用它的好处和坏处分别是什么?
    答:只要在js文件的第一行加上use steict就是开启严格模式,严格模式下的this不是指向window,指向的是undefined,帮助我们养成良好的代码习惯,有一些不严谨的代码会报错。
    9、什么是事件循环(event loop)?
    js是单线程的,也就是说一个时间只能做一件事,做什么事都要排队,想要同一时间做多件事情,这就衍生出了异步,将事件放在消息队列里,先执行可以直接执行的操作,之后不停的去询问消息队列:有没有要执行的?如果有就取出来放到主线程里执行,如果没有就继续之前的操作。举个例子:

    console.log('start')
    
    setTimeout(function() {
        console.log('setTimeout')
    }, 0)
    
    console.log('end')
    // start
    // end
    // setTimeout
    

    在上述的例子中两个console是同步代码,所以直接进入主线程的执行栈中执行,setTimeout是异步代码所以放到消息队列里。在执行栈中按照代码从上到下的执行顺序,打印 start => end。执行栈中的任务全部完成后,对消息队里进行轮询,由于定时器设定的时间为0,所以会在执行栈的任务清空后立即执行,所以上述例子的打印结果为start => end => setTimeout

    大致总结js事件线程循环的过程:
    1、所有任务都在主线程上执行,形成一个执行栈。
    2、所有执行栈中的所有同步任务执行完毕,js就会读取息队列中的异步任务,如果有可以执行的任务就把他放在执行栈中并开始执行。
    3、主线程不断重复上面第二步,这样的一个循环成为事件循环。
    js事件循环中有异步队列有两种:宏任务队列(macro)和微任务队列(micro)
    常见的宏任务比如:setTimeout、setInterval、 setImmediate、script(整体代码)、 I/O 操作、UI 渲染等。
    常见的微任务比如:process。nextTick、Pormise、MutationObserver 等。
    eventLoop循环过程:
    1、初始状态:微任务队列只有一个script脚本;(整体代码为宏任务)
    2、【宏任务阶段】执行script代码,创建宏任务到宏任务调用栈中,创建的微任务到微任务调用栈中。
    3、【微任务阶段】执行微任务,调出当前微任务中的所有微任务,一次性执行,其中如果有宏任务推到宏任务栈中。
    4、【宏任务阶段】执行宏任务,调用当前宏任务栈中的第一个宏任务,其中有创见的微任务推到微任务栈中。
    5、如果代码没结束,循环执行3、4步骤。
    总结:
    1、宏任务和微任务是交替进行的
    2、每个宏任务只执行栈中的第一个任务,执行完就执行微任务。微任务执行栈中所有的微任务。

    console.log('sync');
     
    setTimeout(function () {
       console.log('setTimeout')
    }, 0);
     
    var promise = new Promise(function (resolve, reject) {
       console.log('promise');
       setTimeout(function() {
          promise.then(function(){
            console.log('promise-setTimeout-then')    
          })
          console.log('promise-setTimeout')
       }, 0);
       resolve();
    });
     
    promise.then(function() {
        setTimeout(function() { 
                promise.then(function(){
                    console.log('then-setTimeout-then')    
                })
                console.log('then-setTimeout')
        }, 0);
        console.log('then');
        promise.then(function(){
            console.log('then-than')    
        })
    })
    ////宏任务阶段
    sync  
    promise
    //微任务阶段
    then
    then - than
    //宏任务阶段
    setTimeout
    //微任务阶段(没有任务,没有输出)
    //宏任务阶段
    promise - setTimeout
    //微任务阶段
    promise - setTimeout - then
    //宏任务阶段
    then - setTimeout
    //微任务阶段
    then-setTimeout-then
    

    如果不清楚请跳转链接:https://blog.csdn.net/webjhh/article/details/116759051
    10、请解释同步和异步的区别。
    11、http的状态码
    答:1信息,服务器接收到请求,请求者继续吧
    2
    成功。
    3重定向,需要进一步操作来完成请求
    4
    客户端错误
    5**服务端错误
    16、浏览器的垃圾回收机制是什么?
    12、构造函数new的过程
    1、创建一个新对象
    2、把当前构造函数的作用域给新的对象(此时this指向就会指向新对象)
    3、执行构造函数中的代码(给新的对象添加方法或者是属性)
    4、返回新对象
    通过new关键字创建的对象会有一个constructor属性,该属性指向的是当前的这个对象。
    注意:原本构造函数是window对象的方法,如果不是用new调用,那么指向的还是window,那么this指向也是window。如果是用new关键字调用,那么this指向就是当前的对象。
    13、如果后端给前端一个很大的数,前端要怎么处理?
    答:分页,滚动加载,加lodding,节流。
    14、函数的节流和防抖
    函数节流是指一定时间内js方法只跑一次
    函数防抖是指频繁触发的情况下,只有足够的空闲时间,才执行代码一次。
    函数防抖的要点,也是需要一个setTimeout来辅助实现。延迟执行需要跑的代码。
    如果方法多次触发,则把上次记录的延迟执行代码用clearTimeout清掉,重新开始。
    如果计时完毕,没有方法进来访问触发,则执行代码。

    相关文章

      网友评论

          本文标题:基础面试题js

          本文链接:https://www.haomeiwen.com/subject/sulgfltx.html