对以下代码片段中“this”值更改的说明

  • 本文关键字:说明 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('2', this)
  })
}
obj.test()()

上面的代码记录

// 0 Window
// 1 Object
// 2 Window
// 3 Window

我很难理解是什么决定了this的价值应该是什么。

// 0 Window有意义的,因为这是第一次调用 wrap 的时间,此时不应将其值this设置为 obj

// 1 Object是有道理的obj.test现在等于 function x() ,它正确地将this记录为obj

// 2 Window 我不确定为什么会发生这种情况。为什么this的值不会传播到func()?我认为this应该指的是函数的所有者。这是否意味着即使function y()是在 obj 内部创建的,它也以某种方式被吊到窗户上?

// 3 Window 同样function z()为什么this的价值不是从function x()传下来的。this的价值不是应该在那里传播吗?

"this"绑定非常令人困惑。但是,如果您记住以下这些规则,则会更容易理解。根据Javascript文档,在这些顺序中,"this"绑定有四条规则:

  1. 新运算符
  2. 通过调用或应用方法显式或硬绑定
  3. 与包含对象的隐式绑定,如对象的方法
  4. 默认值(全局(

从脚本中,只有规则 #3 和 #4 适用,因为没有新的运算符和调用或应用方法。

所以解释是:

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

1 个对象 - 规则 #3 与包含对象的隐式绑定,就像对象的方法一样,obj.test 在你的例子中

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

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

接下来,本文最准确的指导,按顺序,函数调用脱糖

  • wrap.call(window, function() {})
  • obj.test.call(obj)
  • y.call(window)
  • z.call(window)

要记住的是,this不会通过函数声明传播。this的值完全取决于函数的调用方式。

我感到困惑的原因是因为我有点太习惯了箭头函数,它为你保留了this的价值。

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

这种脱糖到

function wrap(func) {
  var _this = this;
  return function () {
    console.log(_this);
    return function () {
      console.log(_this);
      func()
      return function () {
        return console.log(_this);
      };
    };
  };
}

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

相关内容

最新更新