将对象分配给原型

assigning object to prototype

我正在尝试将一个对象分配给一个原型,但我一直收到该对象未定义的错误消息。我正在尝试这样做

//x.prototype.y = {};
StreetEasy.prototype.neighborhoodPaths = {};

稍后在代码中我试图在另一个原型函数中访问该对象并使用

推送新数据
//x.prototype.assignData = function(z, a){
  // this.y[z] = a;
//}
StreetEasy.prototype.findNeighborhoodPath = function(areaQuery, callback){
  var data = {q: areaQuery, key: this.apiKey, format: this.format};
  var query = qs.stringify(data);
  var url = AreaSearchUrl + '?' + query;

  var areaQ = areaQuery.toLowerCase();
  if (this.neighborhoodPaths[areaQ]) {
      callback(this.neighborhoodPaths[areaQ].path);
   } else {
      http.get(url, function(response){
        response.setEncoding('utf8');
        response.on('data', function (rData){
          rData = JSON.parse(rData);
          callback(rData);
          rData.areas.every(function(element){
    -----------error is here-> this.neighborhoodPaths[element.name.toLowerCase()].path = element.path;
          });

        }).on('error', function(e){
               console.error('ERROR: ' + e.message + ' | ' + e.statusCode );
      });
    });
  }
};

节点不断返回

TypeError:无法读取未定义的 属性 z。我做错了什么?

编辑更多代码:

StreetEasy.prototype.neighborhoodPaths = {}; 
StreetEasy.prototype.findNeighborhoodPath = function(areaQuery, callback){
  var data = {q: areaQuery, key: this.apiKey, format: this.format};
  var query = qs.stringify(data);
  var url = AreaSearchUrl + '?' + query;

  var areaQ = areaQuery.toLowerCase();
  if (this.neighborhoodPaths[areaQ]) {
      callback(this.neighborhoodPaths[areaQ].path);
   } else {
      http.get(url, function(response){
        response.setEncoding('utf8');
        response.on('data', function (rData){
          rData = JSON.parse(rData);
          callback(rData);
          rData.areas.every(function(element){
    -----------error is here-> this.neighborhoodPaths[element.name.toLowerCase()].path = element.path;
          });

        }).on('error', function(e){
               console.error('ERROR: ' + e.message + ' | ' + e.statusCode );
      });
    });
  }
};

(请参阅下面的更新,既然您已经发布了代码。)

这很可能是您调用方式的结果 assignData。这会起作用,例如:

var obj = new x();
obj.assignData("foo", "bar");

这不会:

var obj = new x();
f = obj.assignData;
f("foo", "bar");

出于同样的原因,这不会:

callMeBack(obj.assignData, "foo", "bar");
function callMeBack(method, z, a) {
    method(z, a);
}

在这两种情况下,问题是 assignData 调用中的 this 没有引用对象,而是全局对象。当您通过 属性 引用调用函数 not 时,this 被设置为全局对象(在松散模式下;在严格模式下它将是 undefined).这是通过 属性 引用 调用它 的操作,将 this 设置为 属性 来自的对象。

更多 (在我的博客上)


更新,现在您已经发布了代码。我假设 findNeighborhoodPath 是您在原始问题中调用 assignData 的函数。

问题确实是你输了 this,但不是上面的方式。

您传递的回调 http.get 将通过 this 引用全局对象,而不是调用 findNeighborhoodPath 的实例;同样,您传递给 Array#every 的回调将 this 引用全局对象,因为您没有告诉它做其他事情。

如果你想使用那个实例,最简单的方法是声明一个引用它的变量,然后使用这个变量:

var self = this; // <== Variable to remember `this`
http.get(url, function(response) {
    response.setEncoding('utf8');
    response.on('data', function(rData) {
        rData = JSON.parse(rData);
        callback(rData);
        rData.areas.every(function(element) {
            self.neighborhoodPaths[element.name.toLowerCase()].path = element.path;
        //  ^^^^ --- using it
        });

    }).on('error', function(e) {
        console.error('ERROR: ' + e.message + ' | ' + e.statusCode);
    });
    // ...
});

或者,您可以使用 Function#bindArray#everythisArg 参数:

http.get(url, function(response) {
    response.setEncoding('utf8');
    response.on('data', function(rData) {
        rData = JSON.parse(rData);
        callback(rData);
        rData.areas.every(function(element) {
            this.neighborhoodPaths[element.name.toLowerCase()].path = element.path;
        }, this); // <=== Note passing `this` as the second arg to `every`

    }).on('error', function(e) {
        console.error('ERROR: ' + e.message + ' | ' + e.statusCode);
    });
    // ...
}.bind(this)); // <=== Note the .bind(this)

在 JavaScript 的下一个版本中,ECMAScript6,我们将拥有 "fat arrow" 函数,这些函数具有 "lexical this binding," 一个奇特的术语,意思是函数内的 this 将是在创建函数的上下文中与 this 相同。因此,一旦 V8 支持它们,并且 Node 更新为使用该版本的 V8(这两个都会很快),您将能够执行此操作(注意下面的两个 =>):

http.get(url, (response) => {
    response.setEncoding('utf8');
    response.on('data', function(rData) {
        rData = JSON.parse(rData);
        callback(rData);
        rData.areas.every((element) => {
            this.neighborhoodPaths[element.name.toLowerCase()].path = element.path;
        });

    }).on('error', function(e) {
        console.error('ERROR: ' + e.message + ' | ' + e.statusCode);
    });
    // ...
});