js面试必会题2.0

82 阅读2分钟

七、this不同场景,如何取值?

this易混场景

1.普通函数下的this

2.call apply bind的this

3.定时器中的this

4.箭头函数中的this

        // 1.普通函数中的this
        // 非严格模式 this ->window
        // 严格模式下 this->undefined

        "use strict" //严格模式开关
        function a() {
            console.log(this);
        }
        a();
    // 2.call apply bind 中的this
    // 情况1: this->window
        // a.call()           window
        // a.call(undefined)  window
        // a.call(null)       window
    // 情况2:传什么,this就是什么
    function a() {
        console.log(this);
    }
    a.call()
    a.call(undefined)
    a.call(null)
    a.apply()
    // 都是window

    a.apply("abc")
    a.call(123)
    const fn = a.bind({x:100})
    fn()
      // 3.定时器中的this
      // 情况1:定时器+function this->window
      // 情况2:定时器+箭头函数 this->上层作用域的this

      // 情况1: 只要计时器里面是这种function,都输出window
      // 案例一
          // setTimeout(function () {
          //     console.log(this); //输出 window
          // },100)
      // 案例二
      // function fn() {
      //     setTimeout(function(){
      //         console.log(this);
      //     },100)
      // }
      // fn.call({x:101})  //输出 window
      // 案例三
      // const a={
      //     fn(){
      //         setTimeout(function () {
      //             console.log(this); //输出 window
      //         },100)
      //     }
      // }
      // a.fn()

      // 情况2:
      // 案例一
      // class Obj{
      //     fn(){
      //         setTimeout(()=>{
      //             console.log(this);  //输出Obj
      //         },100)
      //     }
      // }
      // const o =new Obj()
      // o.fn()
      //案例二
      // function fn() {
      //     setTimeout(()=>{
      //         console.log(this); //输出{x:100}
      //     },100)
      // }

      // fn.call({x:100})
 
    /*4.箭头函数中的this
    情况1:有function作用域的,this是上层作用域的this
    情况2:没有function作用域的,this是window*/
    // 案例一:obj1是new Obj 是有作用域的
    class Obj{
        say=()=>{
            console.log(this);
        }
    }
    const obj1=new Obj()
    obj1.say() //输出Obj
    // 案例二:obj2是被定义出来的,没有作用域
    const obj2={
        say:()=>{
            console.log(this);
        }
    }
    obj2.say()  //输出window

    // 案例三
    const oBtn=document.getElementById("btn")
    //有作用域
    // oBtn.onclick=function(){
    //     console.log(this); //输出<button id="btn">test</button>
    // }
    // 没有作用域
    // oBtn.onclick=()=>{
    //     console.log(this);// 输出window
    // }

      let obj={
          x:123,
          show(){
              setTimeout(()=>{
                  console.log(this.x);
              },100)
          }
      }
      obj.show(); //123
      obj.show.call({x:100}) //100

八、手写bind函数

知识点

function.pototype.myBind

Array.prototype.slice.call()

array.shift()

// 原生bind
      //     function fn(a,b,c){
      //         console.log(this);
      //         console.log(a,b,c);
      //         return "this is return"
      //     }
      //    const cb= fn .bind({x:200},1,2,3)
      //    console.log(cb());

      //    手写bind
      Function.prototype.myBind = function () {
        const fn = this;
        // arguments是传进来的所有参数
        // 是一个类数组
        const arg = Array.prototype.slice.call(arguments);
        const _this = arg.shift();
        // const _this=arguments[0]
        return function () {
          return fn.apply(_this, arg);
        };
      };
      const cb = fn.myBind({ x: 2100 }, 1, 2, 3, 4);

      function fn(a, b, c,d) {
        console.log(this);
        console.log(a, b, c,d);
        return "this is return";
      }
      console.log(cb());

九、闭包

什么是闭包

概念:闭包是作用域的一种特殊应用

触发闭包的情况

1.函数当做返回值被返回

2.函数当做参数被传递

3.自执行匿名函数

闭包的应用

1.隐藏变量

2.解决for i 的问题

作用域

全局作用域

局部作用域

自由变量

不在自己作用域里的变量,就是自由变量

自由变量的值:函数定义的地方向上层作用域查找。与调用位置无关

触发闭包的情况

       // 情况1:函数当做返回值被返回
        function fn() {
            const a=1;
            return function(){
                console.log(a);
            }
        }
        let a=5;
        const cb=fn();
        cb();
    // 情况2:函数当做参数传递
    function fn(cb) {
        const a=100;
        cb();
    }
    let a=500;
    fn(function () {
        console.log(a);
    });
    
        // 情况3:自执行匿名函数
        (function (index){
            console.log(index);
        })(10);

闭包的应用

  <body>
    <button>0</button>
    <button>1</button>
    <button>2</button>
    <button>3</button>
    <button>4</button>
  </body>
  <script>
    const aBtn = document.getElementsByTagName("button");
    for (var i = 0; i < aBtn.length; i++) {
      (function (index) {
        aBtn[i].onclick = function () {
          console.log(index);
        };
      })(i);
    }
    
    //其实一个let就可以解决
    // for (let i = 0; i < aBtn.length; i++) {
    //   aBtn[i].onclick = function () {
    //     console.log(i);
    //   };
    // }
  </script>

隐藏变量

    function fn() {
      const data={}
      return {
        set:function(key,val){
          data[key]=val;
        },get:function(val){
          return data[val]
        },
      }
    }
    const json=fn();
    json.set("age",18);
    console.log((json.get("age")));