美文网首页python学习
JavaScript面试题总结

JavaScript面试题总结

作者: 程序小小黑 | 来源:发表于2020-11-12 10:22 被阅读0次

    前端面试题总结
    JavaScript面试题总结
    CSS面试题总结
    VUE面试题总结

    模拟new

    new操作符做了这些事:

    • 它创建了一个全新的对象
    • 它会执行[[Prontotype]] (也就是proto)
    • 它使this指向新创建的对象
    • 通过new创建的对象将最终被[[Prototype]]链接到这个函数的prototype对象上
    • 如果函数没有返回对象类型Object(包含Function,Array,Date,RegExg,Error),那么new表达式中的函数调用将返回该对象引用
    function objectFactory() {
      const obj = new Object(); // 用new Object() 的方式新建了一个对象 obj
      const Constructor = [].shift.call(arguments); // 取出第一个参数,就是我们要传入的构造函数。此外因为 shift 会修改原数组,所以 arguments 会被去除第一个参数
      obj.__proto__ = Constructor.prototype; // 将 obj 的原型指向构造函数,这样 obj 就可以访问到构造函数原型中的属性
      const ret = Constructor.apply(obj, arguments); // 使用 apply,改变构造函数 this 的指向到新建的对象,这样 obj 就可以访问到构造函数中的属性
      return typeof ret === "object" ? ret : obj; // 判断返回的值是不是一个对象,如果是一个对象,我们就返回这个对象,如果没有,我们该返回什么就返回什么。
    }
    

    bind、call、apply 区别

    call 和 apply 都是为了解决改变 this 的指向。作用都是相同的,只是传参的方式不同。
    除了第一个参数外,call 可以接收一个参数列表,apply 只接受一个参数数组。
    bind 和其他两个方法作用也是一致的,只是该方法会返回一个函数。并且我们可以通过 bind 实现柯里化。

    let a = {
        value: 1
    }
    function getValue(name, age) {
        console.log(name)
        console.log(age)
        console.log(this.value)
    }
    getValue.call(a, 'vue', '24')
    getValue.apply(a, ['vue', '24'])
    getValue.bind(a, 'Vue', '24')()
    

    bind的模拟实现

    bind() 方法会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。(来自于 MDN )

    Function.prototype.bind2 = function (context) {
    
        if (typeof this !== "function") {
          throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
        }
    
        var self = this;
        var args = Array.prototype.slice.call(arguments, 1);
    
        var fNOP = function () {};
    
        var fBound = function () {
            var bindArgs = Array.prototype.slice.call(arguments);
            return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
        }
    
        fNOP.prototype = this.prototype;
        fBound.prototype = new fNOP();
        return fBound;
    }
    

    箭头函数的特点

    箭头函数其实是没有 this 的,这个函数中的 this 只取决于他外面的第一个不是箭头函数的函数的 this。并且 this 一旦绑定了上下文,就不会被任何代码改变。

    闭包

    闭包的定义很简单:函数 A 返回了一个函数 B,并且函数 B 中使用了函数 A 的变量,函数 B 就被称为闭包。

    function A() {
      let a = 1
      function B() {
          console.log(a)
      }
      return B
    }
    

    你是否会疑惑,为什么函数 A 已经弹出调用栈了,为什么函数 B 还能引用到函数 A 中的变量。因为函数 A 中的变量这时候是存储在堆上的。现在的 JS 引擎可以通过逃逸分析辨别出哪些变量需要存储在堆上,哪些需要存储在栈上。

    经典面试题,循环中使用闭包解决 var 定义函数的问题
    for (var i=1; i<=5; i++) {
        setTimeout( function timer() {
            console.log( i );
        }, i*1000 );
    }
    

    首先因为 setTimeout 是个异步函数,所有会先把循环全部执行完毕,这时候 i 就是 6 了,所以会输出一堆 6。
    解决办法三种,第一种使用闭包

    for (var i = 1; i <= 5; i++) {
      (function(j) {
        setTimeout(function timer() {
          console.log(j);
        }, j * 1000);
      })(i);
    }
    

    第二种就是使用 setTimeout 的第三个参数

    for ( var i=1; i<=5; i++) {
        setTimeout( function timer(j) {
            console.log( j );
        }, i*1000, i);
    }
    

    第三种就是使用 let 定义 i 了

    for ( let i=1; i<=5; i++) {
        setTimeout( function timer() {
            console.log( i );
        }, i*1000 );
    }
    

    相关文章

      网友评论

        本文标题:JavaScript面试题总结

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