关于this的面试题,让你彻底解决this 的指向问题

271 阅读4分钟

高阶函数this的指向

环境对象this

1.环境对象 this : 谁调用我,我就指向谁 普通函数; 函数名() this指向window 对象方法: 对象名.方法名() this指向对象 构造函数; new 函数名() this指向new创建的实例对象 总结:this指向三选一, 先找new, 再找点

        ***默认情况下,函数内的this是固定的,无法修改
        ***如果想动态修改函数内部的this指向,则需要上下文调用方法
        *上下文 : 函数作用域   上下文指向, 修改函数作用域this的指向
        
        
            console.log(this)
        }
        // 普通函数
        fn() //this指向window
        // 构造函数
        new fn() //this指向new创建的实例对象
        //对象方法
        let obj = {
            name: '张三',
            eat: fn
        }
        obj.eat() //this指向对象

如何修改this指向

上下文调用 : 修改函数内部this

1 函数名 : call(修改的this,参数1,参数2,参数3)

    function fn(a, b) {
      console.log(this);
      console.log(a + b);
    }


    //(1) 函数名.call(修改的this,参数1,参数2...)
    fn.call({
      name: '张三'
    }, 10, 20)

2 函数名 : apply(修改的this,数组/伪数组)

    function fn(a, b) {
      console.log(this);
      console.log(a + b);
    }
    // (2) 函数名.apply(修改的this,数组/伪数组)
    // **apply 会自动遍历数组和伪数组,然后逐一传参
    fn.apply({
      name: '李四',
      agr: 19,
      sex: '男'
    }, [40, 50])


3 函数名 : bind(修改的this)

    function fn(a, b) {
      console.log(this);
      console.log(a + b);
    }
     // (3)函数名bind(xuigai this)
    // bind 不会立即执行函数,而是得到一个修改this之后的新函数
    let newFn = fn.bind({
      name: '王五'
    })
    newFn(40, 20)

bind()场景:修改定时器的this

变量 : 是内存空间,只有存储功能,没有运算功能 变量 只有两种语法 存 取 字面量 :是数据 只有运算功能,没有运算功能

    bind()场景:修改定时器的this
    */
    //  定时器中的this指向window ,如果修改定时器this,就需要用bind

    let fn = function () {
      console.log(this);
    }
    let newFn = fu.bind({
      name: '张三'
    })

    setTimeout(newFn, 2000);

    // 上面步骤可以简洁一行
    setTimeout(function () {

    }.bind({
      name: '王五'
    }), 1000)

闭包的定义(面试题!!!!!)

       闭包closure是什么 : 两个条件  1.函数   2.函数内部还要访问 其他函数内部变量
        (1) 闭包是一个,访问其他函数内部变量 的函数
        (2)闭包 = 函数 + 上下文引文
        2.闭包作用 :变量污染
            *实际开发中,闭包一般用于回调函数
   
      */
        // 点击搜索按钮
        document.querySelector('.btn').addEventListener('click', function () {
            let text = document.querySelector('input').value
            // 模拟网络请求
            setTimeout(function () {
                alert(`${text}的请求结果为:123456`)
            }, 1000)
        })

结论:一个函数内使用了外部的变量,那这个函数和被使用的外部变量一起被称为闭包结构,在实际开发中,通常会再使用一个函数包裹住闭包结构,以起到对变量保护的作用。

递归函数(面试题!!!!!)

  • 1.递归函数:一个函数自己调用自己

  • 2.递归函数特点

    a.一定要有结束条件,否则会导致死循环
    b.能用递归函数实现的需求,就一定可以用循环调用函数来解决,只是代码简洁与性能不同而已
    

递归应用场景:浅拷贝与深拷贝

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>
        /* 
        1. 递归函数 : 在函数中自己调用自己

        2. 递归特点
            a. 能用递归实现的功能一定可以用循环,只是语法不同
            b. 递归一定要有结束的条件,否则会导致死循环
         */

        //一个函数递归
        // function fn(){
        //     console.log('哈哈');
        //     fn();
            
        // };

        // fn();

        //两个函数递归
        // function fn1(){
        //     console.log('哈哈');
        //     fn2();
            
        // };

        // function fn2(){
        //     console.log('呵呵');
        //     fn1();
            
        // };
        // fn2();


        //需求:写一个函数,打印三次 小明你真棒

        let i = 1;
        function fn(){
            console.log('小明你真棒');
            i++;
            if(i <= 3){
                fn();
            };
            
            //循环实现
            // for(let i = 1;i<=3;i++){
            //     console.log('小明你真棒');
                
            // };
        };

        fn();
    </script>
</body>
</html>

总结面试题

this三种指向

this : 谁 `调用` 我,我就指向谁 1.全局函数 : this指向window

2.对象方法 : this指向对象

3.构造函数 : this指向new创建的空对象

call、apply、bind区别

相同点:都是修改函数this指向

不同点

    传参方式不同: call用于单个参数,apply用于多个参数

    执行机制不同: call与apply会立即执行, bind不会立即执行

       call、apply用一次修改一次
       bind;一次修改,终生有效

闭包

什么是闭包:以下两种回答都可以

   闭包是一个访问其他函数内部变量的函数
   闭包是 函数 + 上下文引用组合

   闭包作用:解决变量污染

递归

什么是递归:函数内部调用自己

递归场景

   深拷贝
   遍历dom树