为什么“ this”在下面的代码片段中引用Window对象?

时间:2018-07-02 03:38:23

标签: javascript this

有人可以帮助我理解为什么下面的代码打印 Inside splitName function = [object Window]
为什么“这”是指Window对象?

let emp = {
  fName: '',
  lName: '',
  setName: function(name) {
    console.log("Inside setName function = " + this)
    let splitName = function(n) {
      console.log("Inside splitName function = " + this)
      let nameArr = n.split(' ');
      this.fName = nameArr[0];
      this.lName = nameArr[1];
    }
    splitName(name);
  }
}

emp.setName('ABC DEF');
console.log(window.fName);

5 个答案:

答案 0 :(得分:0)

可以使用Function#call()来传递对象上下文

let emp = {
  fName: '',
  lName: '',
  setName: function(name) {
    console.log("Inside setName function = " + this)
    let splitName = function(n) {
      console.log("Inside splitName function = " + this)
      let nameArr = n.split(' ');
      this.fName = nameArr[0];
      this.lName = nameArr[1];
    }
    splitName.call(this, name);
  }
}

emp.setName('ABC DEF');
console.log(emp.fName);

答案 1 :(得分:0)

我建议将您的方法splitName更改为对象上的方法。这样,它将知道this将引用您的对象emp。否则,因为它是一个独立的函数,这意味着this在默认情况下将引用window,因为没有调用上下文。

let emp = {
  fName: '',
  lName: '',
  splitName: function(n) {
    console.log("Inside splitName function = " + this)
    let nameArr = n.split(' ');
    this.fName = nameArr[0];
    this.lName = nameArr[1];
  },
  setName: function(name) {
    console.log("Inside setName function = " + this)
    this.splitName(name);
  }
}

emp.setName('ABC DEF');
console.log(window.fName);
console.log(emp.fName);

答案 2 :(得分:0)

将您的splitName函数声明更新为Arrow函数,然后它将其作为父级的作用域,并且将按预期工作。

您可以了解how "this" works here
并了解Arrow functions here.

let emp = {
  fName: '',
  lName: '',
  setName: function(name) {
    console.log("Inside setName function = " + this)
    let splitName = (n) => {
      console.log("Inside splitName function = " + this)
      let nameArr = n.split(' ');
      this.fName = nameArr[0];
      this.lName = nameArr[1];
    }
    splitName(name);
  }
}

emp.setName('ABC DEF');
console.log(emp.fName + ' ' + emp.lName );
console.log(window.fName);

答案 3 :(得分:0)

由于上下文和词法作用域Lexical Scope以及javascript中的执行上下文。在javascript中,每个函数(非箭头)都具有执行上下文,而ES6 箭头函数没有自己的执行上下文。

对于构造函数,当我们使用新的javascript引擎初始化构造函数时,您会为其创建执行上下文,并将其分配给它。但是对于非构造函数,如果未使用function.Call或function调用它们,则应用即未设置,则由于词法作用域,它们将窗口范围视为最外部范围。

在浏览器控制台中尝试setContentOffset:animated:,这将打印Window(因为它是DOM的父对象或最外部作用域)。

还可以查看thisHow does the "this" keyword work?

答案 4 :(得分:0)

您可以使用Apply函数将内部函数的内容绑定到封闭的对象。发生这种情况的原因是,在这种类型的闭包中,是指窗口范围(全局范围)。

let emp = {
  fName: '',
  lName: '',
  setName: function(name) {
    console.log("Inside setName function = " + this)
    let splitName = function(n) {
      console.log("Inside splitName function = " + this)
      let nameArr = n.split(' ');
      this.fName = nameArr[0];
      this.lName = nameArr[1];
    }
    splitName.apply(emp,[name]);
  }
}
emp.setName('ABC DEF');
console.log(window.fName);