javascript范围以及关于这个'

时间:2018-03-11 13:08:01

标签: callback closures this bind arrow-functions

我试图深入理解' 这个'适用于javascript。 到目前为止,我所知道的 this

  1. 每个函数都有属性,每当函数执行时,它都会新定义 this 属性。

  2. 指的是调用函数的对象(包括浏览器中的窗口对象)。

  3. 指的是对象的范围(定义对象的位置),而不是在定义函数时使用箭头语法时引用对象本身,因为箭头函数不是新的定义自己的 this

  4. 以下示例旨在帮助您理解

    的行为

    
    
    class Example {
    
      constructor() {
        this.name = 'John';
      }
    
      method1() { //case1 : Closure
        console.log(this.name);
    
        function method2() {
          console.log(this.name);
        }
    
        method2();
      }
    }
    
    const a = new Example()
    a.method1();
    
    
    

    
    
    function testing(callback) {
      return callback();
    }
    
    class Example2 {
    
      constructor() {
        this.name = 'John';
      }
    
      method1() { //case2: callback
        console.log(this.name);
    
        testing(function() {
          console.log(this.name);
        })
      }
    }
    
    const b = new Example2()
    b.method1();
    
    
    

    
    
    function testing(callback) {
      return callback();
    }
    
    class Example3 {
    
      constructor() {
        this.name = 'John';
      }
    
      method1() { //case3: arrow syntax callback
        console.log(this.name);
    
        testing(() => {
          console.log(this.name);
        })
      }
    }
    
    const c = new Example3()
    c.method1(); // logs 'John'
    // logs 'John'
    
    
    

    
    
    function testing(callback) {
      return callback();
    }
    
    class Example4 {
    
      constructor() {
        this.name = 'John';
      }
    
      method1() { // case4: calling method as callback
        console.log(this.name);
      }
    
      render() {
        testing(this.method1)
    
      }
    }
    
    const d = new Example4()
    d.render()
    
    
    

    
    
    function testing(callback) {
      return callback();
    }
    
    class Example5 {
    
      constructor() {
        this.name = 'John';
        this.method1 = this.method1.bind(this);
      }
    
      method1() { //case5: bind method && calling method as callback 
        console.log(this.name);
      }
    
      render() {
        testing(this.method1)
    
      }
    }
    
    const d = new Example5()
    d.render()
    
    
    

    我想知道上面这些情况是如何不同的以及 this 在每个内部函数和回调中引用的内容。你能解释一下吗?谢谢你:))

1 个答案:

答案 0 :(得分:1)

由于深入的精确解释可能非常大而且无聊,这里有exceptional article by kangax完美地解释它。

为了以防万一,如果你需要一个简短而超精简的版本,请点击我的简短版本:

当您调用某个函数时,this由特定base value确定,.通常指向MemberExpression左侧的内容 在x.y()this === x x.y.z()以及this === x.y CallExpression

如果简单.没有x(),请说undefined, 隐含地推断基值指向window,在非严格模式下将其转换为全局this,并且在严格模式下保持不变。

这是一般心理模型,应该涵盖了正确绘制a.method1();上下文的所有日常问题的99%。

现在,对于实际案例:

案例1:

a调用的基值为this,因此其正文中的a指向method2,所以这里没有任何意外。 undefined.method2具有隐式基值TypeError,因此您可以明确指出function testing(callback) { return callback(); }

案例2:

callback()
使用隐式baseValue undefined调用

undefined.callback(),即class, 因为传递的函数是在testing(function() { console.log(this.name); })

中声明的
undefined

触发严格的代码执行模式,这就是为什么window不会再次转换为全局testing(() => { console.log(this.name); }) ,因此我们会遇到与以前相同的错误。

案例3:

箭头功能

this

从封闭范围内的var _this = this; testing((function() { console.log(_this.name); }); 创建硬绑定, 基本上在引擎盖下它和写作一样:

this

这就是为什么你将同一个对象解析为this.method

案例4:

好吧,这个很有趣,需要更多的机制解释。

所以当你通过render() { testing(this.method1) } 时:

this.method
  • 您实际传递的不是引用undefined,而是此引用指向的实际基础Function Object值,因此 当它被执行时,它总是指向this.method1here look,所以它几乎是“一成不变”。

当然是因为class再次在严格的上下文中声明,感谢封闭es6 undefinedundefined仍为window而不转换为全局this

案例5:

与箭头功能相同的机制。 Bind创建一个包装函数,该函数保存缓存的.call值,该值不能覆盖.apply=>,与Logger logger = Logger.getLogger( this.getClass().getName() ); 函数中的相同。

希望这有点澄清一点。