代码之家  ›  专栏  ›  技术社区  ›  Jay Jeong

javascript范围和有关“this”的所有内容

  •  1
  • Jay Jeong  · 技术社区  · 7 年前

    我试图深入了解 '在javascript中工作。 我所知道的一切 到目前为止,

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

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

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

    以下示例有助于理解

    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()

    我想知道上述情况有何不同,原因是什么 指内部每个内部函数和回调。你能解释一下吗?谢谢:)

    1 回复  |  直到 7 年前
        1
  •  1
  •   Karen Grigoryan    7 年前

    由于深入而精确的解释可能会非常大和无聊,下面是一个例子 exceptional article by kangax 这完美地展示了它。

    为了以防万一,如果你需要一个简短的超浓缩版本,这里是我的简短和近似:

    #

    调用函数时 this 由特定的 base value 它通常指向 . 在里面 MemberExpression 所以在 x.y() this === x ,和英寸 x.y.z() this === x.y

    如果是简单的 CallExpression 没有 ,只说 x() ,则, 基值被隐式推断为指向 undefined ,在非严格模式下转换为全局 window 在严格模式下保持不变。

    这是一个通用的心智模型,它应该涵盖99%的日常问题 上下文输出正确。

    现在,根据实际情况:

    案例1:

    a.method1(); 调用具有基值 a 所以 身体内部指向 ,所以这里没有什么意外。 method2 具有隐式基值 undefined.method2 ,因此您有 TypeError 其中明确指出。

    案例2:

    function testing(callback) {
      return callback();
    }
    

    callback() 使用隐式baseValue调用 未定义 ,即。 undefined.callback() ,则, 由于传递的函数在 class

    testing(function() {
      console.log(this.name);
    })
    

    这会触发严格的代码执行模式,这就是为什么 未定义 不会再次转换为全局 ,因此,我们的错误与之前相同。

    案例3:

    箭头功能

    testing(() => {
       console.log(this.name);
    })
    

    从创建硬绑定 在封闭范围内, 基本上,在引擎盖下,这与写作是一样的:

    var _this = this;
    testing((function() {
       console.log(_this.name);
    });
    

    这就是为什么要将同一对象解析为

    案例4:

    好的,这个很有趣,需要更多的力学解释。

    所以当你经过的时候 this.method 在中:

    render() {
      testing(this.method1)
    }
    
    • 您实际传递的不是引用 这方法 ,但此引用所指向的实际底层函数对象值 当它被执行时,它的this总是指向 未定义 ,则, here look ,所以这几乎是“一成不变的”。

    是的,当然是从 this.method1 再次在严格上下文中声明,这要感谢包含es6 ,则, 未定义 残余 未定义 不转换为全局

    案例5:

    与箭头功能相同的机制。Bind创建一个包装器函数,该函数保存缓存的 值,无法用替代 .call .apply ,与中相同 => 作用

    希望这能澄清一点这一切。