zoukankan      html  css  js  c++  java
  • 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方法接受的是一个参数数组。

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

  • 相关阅读:
    AX 2012 Security Framework
    The new concept 'Model' in AX 2012
    How to debug the SSRS report in AX 2012
    Using The 'Report Data Provider' As The Data Source For AX 2012 SSRS Report
    Deploy SSRS Report In AX 2012
    AX 2012 SSRS Report Data Source Type
    《Taurus Database: How to be Fast, Available, and Frugal in the Cloud》阅读笔记
    图分析理论 大纲小结
    一文快速了解Posix IO 缓冲
    #转载备忘# Linux程序调试工具
  • 原文地址:https://www.cnblogs.com/yanggb/p/13218404.html
Copyright © 2011-2022 走看看