对象字面量方法的范围

Scope of object literal methods

我目前正在学习 javascript 并试图理解 'this'。在下面的代码中,为什么我无法在我的 render 方法中访问 this.ul? (它说它是未定义的)。我被引导相信 cacheDOM 方法会将 this.ul 绑定到 people 对象,然后该对象的其余部分可以访问该对象。

(function(){

  var people = {
    people: ['Tom', 'Sean'],

    init: function() {
      this.cacheDOM();
      this.render();
    },

    cacheDOM: function() {
      this.input = window.document.querySelector('.input');
      this.button = window.document.querySelector('.button');
      this.ul = window.document.querySelector('.ul');
    },

    render: function() {
      var data = this.people;

      data.map(function(person){
        var li = document.createElement('li');
        li.textContent = person;
        this.ul.appendChild(li);
      });
    }
  };

  people.init();

})();

已修复。添加 var ul = this.ul 到我的渲染函数的顶部,然后允许地图函数正确访问!

Array.prototype.map 方法创建了自己的闭包,因此 this 不会在这里引用 people 对象。您需要绑定 "this" 以作为:

render: function() {
  var data = this.people;

  data.map(function(person){
    var li = document.createElement('li');
    li.textContent = person;
    this.ul.appendChild(li);
  }.bind(this));
}

您可以将传递给 map 的函数绑定到对象文字的上下文:

data.map(function(person){
  var li = document.createElement('li');
  li.textContent = person;
  this.ul.appendChild(li);
}.bind(this));

或更透明:

var iteratee = function(person){
  var li = document.createElement('li');
  li.textContent = person;
  this.ul.appendChild(li);
}
data.map(iteratee.bind(this));

在匿名函数内部 this 没有引用对象字面量。 this 是对被引用范围所有者的引用。在匿名函数中,我很确定 this 是对 global/window 对象的引用。

要访问对象的 ul 成员,您可以像这样使用 JavaScript 的闭包功能。

render: function() {
  var self = this; // here this points to the object literal
  var data = this.people;

  data.map(function(person){
    var li = document.createElement('li');
    li.textContent = person;
    self.ul.appendChild(li);
  });
}

这个参数的值由调用模式决定。

JavaScript中有四种调用模式: 方法调用模式、函数调用模式、构造函数调用 模式和应用调用模式。 检查 this link 以了解这些模式。

检查 render 函数的以下实现;

render: function() {
  var data = this.people;
  var that = this;
  data.map(function(person){
    var li = document.createElement('li');
    li.textContent = person;
    that.ul.appendChild(li);
  });
}

或者您可以将 this 的值作为参数传递给 map() 函数:

  render: function() {
  var data = this.people;
  data.map(function(person){
    var li = document.createElement('li');
    li.textContent = person;
    this.ul.appendChild(li);
  },this);
}