“ this”和ObjectName(例如:Person)有什么区别?

时间:2018-08-08 02:22:32

标签: javascript

谁能告诉我下面两个代码之间的区别:

var Person = {
  Cars: [],
  init: function(){ 
    this.Cars = [];
  } 
};

var Person = {
      Cars: [],
      init: function(){ 
        Person.Cars = [];
      } 
    };

一个正在使用“ this”,另一个正在使用“ Person”。

谢谢

2 个答案:

答案 0 :(得分:1)

在第二个代码中,init总是Cars上创建(或重新分配)Person属性。另一方面,在第一个代码中,在其上创建Cars属性的对象取决于调用上下文。例如,如果将init函数放到另一个对象上然后调用它,则另一个对象将发生变异:

var Person = {
  Cars: [],
  init: function(){ 
    this.Cars = [];
  } 
};

var myVar = {};
myVar.init = Person.init;
myVar.init();
console.log(myVar);

如果使用.call,您可以做同样的事情:

var Person = {
  Cars: [],
  init: function(){ 
    this.Cars = [];
  } 
};

var myVar = {};
Person.init.call(myVar);
console.log(myVar);

引用this时,是指调用上下文,而不是静态变量/对象。

答案 1 :(得分:0)

这里发生了2种不同的事情,因此在尝试进行比较时意识到差异很重要。

var Container = {
  Cars: [],
  init: function() {
    this.Cars = [];
  }
};

var Shipment = {
  Cars: [],
  init: function() {
    Shipment.Cars = [];
  }
};

让我们从第二个开始(命名为Shipment,以便我们更好地区分它们)。

我们拥有的是一个带有单个方法的对象常量,该方法在被调用时会将属性Cars的值分配给数组。

JS将首先尝试查找什么是Shipment及其定义位置。当前词汇范围/上下文中未定义它,因此它将向上一级。并且向上一级直到找到它为止。这就是为什么您也可以通过相同的方法从此处访问Container类的原因。

在这种情况下,由于它是在全局范围内执行init函数之前 定义的,因此可以找到它。因此,我们找到Shipment,然后将数组分配给它。因此,我们所做的实际上是在当前范围之外寻找对象文字,并一直寻找直到找到它为止。如果我们不能JS显然会抛出错误。当您进行use strictdefault binding时,还有很多其他功能,但这可能有点不合时宜。

在第一种情况下,我们要求JS在当前词法上下文中为我们提供方法的所有者。这就是this的含义。猜猜...所有者是Container,对我们来说幸运的是,我们可以按照计划随Cars属性的分配一起移动。

现在请记住,根据执行情况this可能具有very different meaning,对于ES6箭头功能,它将始终为enclosing lexical context。然后,借助ECMAScript 5和诸如callbind之类的功能,您可以基本实现所需的功能(尽管近来在实践中对此并不满意)。但是在这个特定的例子中,我认为应该涵盖大部分内容。

希望这会有所帮助。