• javascript中的this理解


    JavaScript中的this其实是一个很好理解的概念,只不过JavaScript对初学者隐藏了一些细节,促使初学者在理解this的时候对概念会特别模糊,这里来解释一下JavaScript中的this到底是什么东西。

    函数调用中的this

    不知道你有没有发现,在把对象和函数联系起来用的时候,会出现下面这种情况:

    let obj = {
       name: 'yanggb',
       age: 18,
       hello: function(){
          console.log(`你好,我叫${this.name},我今年${this.age}岁了`)
       }
    }
    let sayHi = obj.hello
    sayHi() // 你好,我叫,我今年undefined岁了
    obj.hello() // 你好,我叫yanggb,我今年18岁了

    sayHi函数和obj.hello函数都是相同的打印逻辑(sayHi也是obj.hello赋值给它的),但是打印的结果却不一样,这就是this的妙用了,因为两者的this不是同一个this,所以才会打印出不同的结果。

    要知道它们的this指向,可以在函数调用的时候用call或者apply。

    // 沿用上面的代码
    sayHi.call(undefined) // 你好,我叫,我今年undefined岁了
    obj.hello.call(obj) // 你好,我叫yanggb,我今年18岁了

    可以看到,加上call后并不影响结果。事实上,在函数调用的后面加call才是最完全的写法,不加call的函数调用其实是JavaScript的一个语法糖。call的第一个参数就是这个函数所指向的this,在这里有个公式:

    对象.函数名.call(对象, arguments)

    谁引用了函数,谁就代表this,但如果像sayHi没有对象引用就直接调用的,它默认的this为null或undefined,那么浏览器就会自动把它的this变成window对象(window对象是浏览器内置的全局对象,因为函数是在全局上下文中执行的,this也就被替换成了window全局对象,而window全局对象的name属性是空字符串,window全局对象没有age属性,也就产生了相应的打印结果)。

    []语法中的this

    var length = 10 // 用var把length属性挂载到window全局对象上作为全局属性
    function fn() {
       console.log(this.length)
    }
    let obj = {
       length: 5,
       long: function(fn) {
          fn()
          arguments[0]()
       }
    }
    obj.long(fn, 1)

    先别想这段代码是什么逻辑,我们先把所有的函数调用都加上call。

    // 沿用上面代码
    fn.call(undefined) // 打印出10
    obj.long.call(obj,fn,1)

    在fn和obj.long的调用加上call让结果一目了然,然后我们再给argument[0]调用加上call,直接套公式虽然不符合规范,但可以让我们更好地理解。

    arguments[0].call(arguments) // 打印出 2

    因为在这里的arguments[0]就是fn,this被替换为arguments对象(使用[]语法的对象会作为函数调用方),而arguments的长度是2,所以this.length的结果为2,是不是没想到还能这么用?this实在是太灵活了,其取值决定于函数被谁引用!

    箭头函数

    新出的ES6语法里的箭头函数没有this,所以在你需要用到this的时候最好使用ES5的函数语法。

    而正是因为箭头函数里没有this,所以它才会继承上一层函数的this。这一点要格外注意,它与上一层函数之间并不存在谁指向谁。

    总结

    当你调用一个函数的时候,最好是call一下这个函数,它的第一个参数就代表this,这样有助于你理解代码。具体就是当你遇到一个函数而不清楚它的this到底指向谁的时候,你可以套用公式【对象.函数名.call(对象,arguments)】来帮助理解。

    除了call以外还有apply,和call的功能以及使用方法基本一致,区别只在于call方法接受的是参数列表,而apply方法接受的是一个参数数组。

    "因为我知道的比你多,我比你更懂事,所以日子让我比你更难过。"

  • 相关阅读:
    Springboot + Atomikos + Druid + Mysql 实现JTA分布式事务
    JAVA生成一个二维数组,使中间元素不与相邻的9个元素相等,并限制每一个元素的个数
    java.net.UnknownHostException: lc001 未知的网络服务
    Maven 多模块引用版本的问题 java.lang.NoSuchMethodError
    Maven项目运行Junit测试用例 出现ClassNotFound
    CAS5.X 集群配置 初版
    调试CAS源码步骤
    openhtmltopdf 支持自定义字体、粗体
    Java HTML to PDF 支持SVG
    .Net 框架
  • 原文地址:https://www.cnblogs.com/yanggb/p/13218404.html
Copyright © 2020-2023  润新知