Javascript 下面的代码片段中'this'的值发生变化的原因是什么?

Javascript 下面的代码片段中'this'的值发生变化的原因是什么?,javascript,this,Javascript,This,上面的代码记录 function wrap(func) { console.log('0', this) return function x() { console.log('1', this) func() return function z() { console.log('3', this) } } } var obj = { x: 5, test: wrap(function y() { console.log('

上面的代码记录

function wrap(func) {
  console.log('0', this)
  return function x() {
    console.log('1', this)
    func()
    return function z() {
      console.log('3', this)
    }
  }
}

var obj = {
  x: 5,
  test: wrap(function y() {
    console.log('2', this)
  })
}

obj.test()()
我很难理解是什么决定了这个的值应该是多少

//0窗口
有意义,因为这是首次调用wrap时,此时其值
this
不应设置为
obj

/1对象
有意义
obj。test
现在等于
函数x()
,它将
正确记录为
obj

/2 Window
我不知道为什么会发生这种情况。为什么
this
的值没有传播到
func()
?我想
这个
应该是指函数的所有者。这是否意味着即使在obj内部创建了
函数y()
,它还是以某种方式被吊到了窗口


//3窗口
函数z()类似
为什么
的值没有从
函数x()传下来
this
的值不应该在那里传播吗?

this绑定非常混乱。但是,如果您记住以下规则,就会更容易理解。根据Javascript文档,“this”绑定有四条规则:

  • 新操作员
  • 通过调用或应用方法进行显式或硬绑定
  • 与包含对象的隐式绑定,如对象的方法
  • 默认值(全局)
  • 从脚本中,只有规则3和4适用,因为没有新的运算符和调用或应用方法

    因此,解释如下:

    //0窗口-规则#4默认值(全局)

    //1对象-规则#3包含对象的隐式绑定,如对象的方法,在您的案例中为obj.test

    //2窗口-规则#4默认值(全局)

    //3窗口-规则#4默认值(全局)

    以下是本文最准确的指导,按顺序,函数调用desugar

    • wrap.call(窗口,函数(){})
    • obj.test.call(obj)
    • y.call(窗口)
    • z.call(窗口)
    需要记住的是,
    这个
    不会通过函数声明传播。
    的值完全取决于函数的调用方式

    我之所以感到困惑,是因为我太习惯于使用箭头函数,它为您保留了
    this
    的值

    // 0 Window
    // 1 Object
    // 2 Window
    // 3 Window
    
    这一点很重要

    function wrap(func) {
      return () => {
        console.log(this)
        return () => {
          console.log(this)
          func()
          return () => console.log(this)
        }
      } 
    }
    

    并显示您必须显式传递
    this
    的值。尽管使用箭头函数,但重要的是要注意对
    func
    的调用不会保留
    this
    的值。我需要做
    func.call(this)
    才能做到这一点。

    我相信既然
    func
    被传递给
    wrap
    函数,它将得到与
    wrap
    函数中的
    this
    相同的
    值。耶胡达·卡茨就这个主题写了一篇非常好的博客文章:“这是否意味着,即使函数y()是在obj内部创建的”
    y
    没有在
    obj
    中调用,您似乎感到困惑的是,
    这个
    不像一个变量,它不会保留在一个新的作用域中。它在每个新的作用域中由一组规则确定(其他人已经发布了)。之所以
    1
    this==obj
    是因为函数是直接从对象调用的。在其他情况下,
    this
    有一个新的作用域,并且它不是由对象直接调用的,因此上下文默认为
    window
    @AR7
    return function x(){console.log('1',this)
    obj.test();
    function wrap(func) {
      var _this = this;
    
      return function () {
        console.log(_this);
        return function () {
          console.log(_this);
          func()
          return function () {
            return console.log(_this);
          };
        };
      };
    }