面试专题总结:this指向问题

766 阅读3分钟

简介

拿到 字节跳动实习生offer 总结

回馈分享一波自己的知识点总结

希望读者依此构建自己的知识树(思维导图)

偷懒一下:可参考我自己总结思维导图 : 点这里

附带:高频面试题积累文档。 来自于(学长、牛客网等平台)

自己开发的博客地址:zxinc520.com

github地址: 点击

此篇 js - 【this指向问题】 知识点: 全部弄懂了,面试很容易。

一、this的四条绑定规则

  1. 默认绑定

    • 独立函数调用时,this 指向全局对象(window),如果使用严格模式,那么全局对象无法使用默认绑定, this绑定至 undefined。
  2. 隐式绑定

    • 函数this 是指向调用者 (隐式指向)

      function foo() {
        console.log( this.a);
      }
      var obj = {
        a: 2,
        foo: foo
      };
      obj.foo();  // 2
      
      • obj1.obj2.foo(); // foo 中的 this 与 obj2 绑定
    • 问题:隐式丢失

      • 描述:隐式丢失指的是函数中的 this 丢失绑定对象,即它会应用第 1 条的默认绑定规则,从而将 this 绑定到全局对象或者 undefined 上,取决于是否在严格模式下运行。
      • 以下情况会发生隐式丢失
        1. 绑定至上下文对象的函数被赋值给一个新的函数,然后调用这个新的函数时
        2. 传入回调函数时
  3. 显式绑定

    • 显式绑定的核心是 JavaScript 内置的 call(..) 和 apply(..) 方法,call 和 apply bind的this第一个参数 (显示指向)
  4. new 绑定

    • 构造函数的this 是new 之后的新对象 (构造器)

二、call bind apply

改变函数执行时的上下文(改变函数运行时的this指向)

2.1、apply

  • 第二个参数为数组

  • 自定义实现

    // 自定义apply函数
    Function.prototype.apply1 = function (obj, arg) {
        //context为null或者是undefined时,设置默认值
        if (!obj) {
            obj = typeof window === 'undefined' ? global : window
        }
        obj.fn = this
        let result = null
        //undefined 或者 是 null 不是 Iterator 对象,不能被 ...
        if (arg === undefined || arg === null) {
            result = obj.fn(arg)
        } else {
            result = obj.fn(...arg)
        }
        delete obj.fn
        return result
    }
    

2.2、call

  • 第二个参数为参数列表

  • 自定义实现

    Function.prototype.call1=function (obj,...arg) {
            if (!obj){
                obj = typeof window ==='undefined'?global:window
            }
            obj.fn = this
            let result =null
            result=obj.fn(...arg)
            delete obj.fn
            return result
    }
    

2.3、bind

  • 特点

    • 返回一个函数
    • 可以传入参数(使用bind时和bind新生成的函数都可以传参)
    • 当 bind 返回的函数作为构造函数的时候,bind 时指定的 this 值会失效,但传入的参数依然生效
  • 注意:bind这个方法在IE6~8下不兼容

  • 自定义实现

    Function.prototype.bind1 = function (obj,...arg) {
        if(!obj){
            obj = typeof window === 'undefined'? global : window
        }
        let self = this
        let args = arg
        function f() {}
        f.prototype = this.prototype
        let bound = function () {
            let res = [...args, ...arguments]
            let _this = this instanceof f ? this : obj
            return self.apply(_this, res)
        }
        bound.prototype = new f()
        return bound
    }
    

2.4、区别

call和apply改变了函数的this上下文后便执行该函数,而bind则是返回改变了上下文后的一个函数。

三、相关题目

  1. 怎么利用call、apply来求一个数组中最大或者最小值

    let arr = [1, 2, 19, 6];
    Math.max.call(null, ...arr)
    Math.max.apply(null, arr)
    var fn=Math.max.bind(null,...arr)
    fn()
    
  2. 如何利用call、apply来做继承

  3. apply、call、bind的区别和主要应用场景

    1. 将类数组/含有length属性的对象转化为数组
    2. 求数组中的最大和最小值
    3. 数组追加
    4. 利用call和apply做继承
    5. 判断变量类型