zoukankan      html  css  js  c++  java
  • 前端读者 | 嗨,你知道this吗

    本文来自 @position_柚子,地址:https://juejin.im/post/5995c7a76fb9a0247a60c407

    在平时的代码中,相信大家经常用到 this,可是你真的明白此 this 真的是你认为的 this 吗?今天柚子君总结了一下平时用到的 this 的场景,大家走过路过不要错过啊~

    首先咱们先来看一下《JavaScript 高级程序设计》上是怎么说的。

    this 对象是在运行时基于函数的执行环境绑定的:在全局函数中,this 等于 windows,而当函数被作为某个对象的方法调用时,this 等于那个对象。

    还有一种情况,在《深入理解 ES6》一书中写道:

    如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this,且不能通过 call()、apply() 或 bind() 方法来改变 this 的值。

    首先看一下非箭头函数的情况:

    一、普通函数调用

    这是一个普通的函数声明,在这种情况下,this 是指向 window 的:

    var test = '哈哈哈';
    function thisHandler() {
        console.log('test:',this.test,'this:',this);
    }
    thisHandler() // test: 哈哈哈 this: window
    

    其实上面的代码就相当于 window 调用 thisHandler(),所以这时 this 指向 window

    var b = '哈哈哈';
    function thisHandler() {
        console.log('b:',this.b,'this:',this);
    }
    window.thisHandler() // b: 哈哈哈 this: window
    

    二、作为对象的方法调用

    当作为对象的方法被调用时,this 这时就指向调用它的对象。

    var thisHandler = {
      name: "柚子",
      test: function(){
        console.log('my name:',this.name); 
      }
    }
    thisHandler.test() // my name: 柚子
    

    再来一个栗子:

    var thisHandler = {
      name: "柚子",
      fn: {
        name: '芒果',
        test: function() {
           console.log('my name:',this.name); 
        }
      }
    }
    thisHandler.fn.test() // my name: 芒果
    

    这时 this 指向的是对象 fn 了,所以,关于对象调用这一点明白了吗,如果明白了,那没关系,接着看下一个强化题:

    var name = '柚子'
    var thisHandler = {
      name: "芒果",
      fn: {
        name: '糖果',
        test: function(){
          console.log('my name:',this.name); 
        }
      }
    }
    var testHandler = thisHandler.fn.test
    testHandler()
    

    这里是一秒钟分割线

    哒哒哒,答对了,这里的 this 指向的 window,那么这是为什么呢,哪位小盆友来回答一下。举手:

    上面说到了,this 指向的是最后调用它的对象,第一步是赋值给了 testHandler,最后执行的那一句相当于 window.testHandler()。所以这里的 this 指向的是 window。最后输出的就是 my name: 柚子

    哒哒哒,真聪明,来闯下一关~

    三、构造函数的调用

    var name = '柚子'
    function Bar() {
      this.name = '芒果'
    }
    
    var handlerA = new Bar();
    console.log(handlerA.name);  // 芒果
    console.log(name) // 柚子
    

    其实要明白为什么会是这样一个结果,咱们就要来聊聊 new 做了哪些事情。

    • 创建类的实例。这步是把一个空的对象的 __proto__ 属性设置为 Bar.prototype
    • 初始化实例。函数 Bar 被传入参数并调用,关键字 this 被设定为该实例。
    • 返回实例。

    弄明白了 new 的工作内容,自然而然的也明白了上面输出的原因。

    Bar() 中的 this 指向对象 handlerA,并不是全局对象。

    四、apply / call 调用

    使用 apply 方法可以改变 this 的指向。如果这个函数处于非严格模式下,则指定为 nullundefined 时会自动指向全局对象(浏览器中就是window对象)。

    var name = '芒果';
    var thisHandler = {
      name: "柚子",
      test: function(){
        console.log('my name:',this.name); 
      }
    };
    
    thisHandler.test(); //  my name: 柚子
    thisHandler.test.apply(); // my name: 芒果
    

    四、箭头函数

    在《深入理解 ES6》一书中可以知道箭头函数和普通函数的一个不同之处就在于 this 的绑定。

    箭头函数中没有 this 绑定,必须通过查找作用域链来决定其值。如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this;否则,this 的值会被设置为 undefined

    var name = '柚子'
    var thisHandler = {
      name: '芒果',
      test:() => {
        console.log('my name:',this.name,'this:',this); 
      }
    }
    
    thisHandler.test(); // my name: 柚子 this: Window
    

    这时 this 不是指向 thisHandler,而是 Window

    关于 this 的使用和体会还是要在平时运用中理解,先了解其原理,那么在使用的时候就如鱼得水啦。

  • 相关阅读:
    【集训第二天·翻水的老师】--ac自动机+splay树
    【集训第一天·特来卖萌】树链剖分之水水的例题
    1.ARM寄存器简解
    2.汇编代码的简单实现
    Android之Activity 生命周期
    Android之SQLite
    魅族 -- 禁止D及以下级别LOG的输出
    常用的SQL语句
    Android开发工具
    Android介绍
  • 原文地址:https://www.cnblogs.com/chenrf/p/10018469.html
Copyright © 2011-2022 走看看