开发者问题收集

无法读取未定义的给定属性

2018-01-12
595

我在渲染函数中调用 this.getAllJobsAPI();。

这成功调用了 getAllJobsAPI(如下所示),并且我能够从作业的 JSON 数组中检索作业名称。

getAllJobsAPI(){
var headers = new Headers();
headers.append('Authorization', 'Basic YWRtaW46YWRtaW4=');

fetch('http://localhost:8080/api/json', {headers: headers})
.then((result) => {
  // Get the result
  // If we want text, call result.text()
  return result.json();
}).then((jsonResult) => {
  // get all jobs 
  var jobs = [];

  Object.keys(jsonResult.jobs).forEach(function(key) {
    jobs.push(jsonResult.jobs[key].name);

    var job = jsonResult.jobs[key].name;
    console.log(job);

    this.getLastBuildAPI(job);   

});

//var a = 'meetup';
//this.getLastBuildAPI(a);
console.log(jsonResult);

})
}

但在 for each 循环中调用 this.getLastBuildAPI(job); 会引发“Uncaught (in promise) TypeError: Cannot read property 'getLastBuildAPI' of undefined”错误。但如果我在函数末尾硬编码一个名称变量并调用 this.getLastBuildAPI(a);,我可以获得成功响应。

有人能告诉我为什么我无法在 JSON 数组的 for-each 中调用 this.getLastBuildAPI(job); 吗?请注意,我能够在控制台中看到作业变量。

谢谢,

2个回答

因为解析回调中的 thisundefined (因为它是不同的上下文),而当它在回调之外时, this 就是您期望的对象。您可以先引用 this var 并将其存储起来。

getAllJobsAPI(){
var headers = new Headers();
headers.append('Authorization', 'Basic YWRtaW46YWRtaW4=');
var self = this;

fetch('http://localhost:8080/api/json', {headers: headers})
.then((result) => {
  // Get the result
  // If we want text, call result.text()
  return result.json();
}).then((jsonResult) => {
  // get all jobs 
  var jobs = [];

  Object.keys(jsonResult.jobs).forEach(function(key) {
    jobs.push(jsonResult.jobs[key].name);

    var job = jsonResult.jobs[key].name;
    console.log(job);

    self.getLastBuildAPI(job);   

});

//var a = 'meetup';
//this.getLastBuildAPI(a);
console.log(jsonResult);

})

您也可以应用其他方法。

1. 使用 bind 方法。

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

Object.keys(jsonResult.jobs).forEach(function(key) {
    jobs.push(jsonResult.jobs[key].name);
    var job = jsonResult.jobs[key].name;
    console.log(job);
    this.getLastBuildAPI(job);   
}.bind(this));

2.使用 arrow 函数。

直到 arrow 函数,每个 new 函数 都定义了自己的 this 值。

例如,在构造函数的情况下, this 可以是一个新的对象。

function Person(age){
  this.age=age;
  console.log(this);
}
let person=new Person(22);

或者,如果可以像 obj.getAge() 那样访问创建的函数,则 this 可以 指向 base 对象。

let obj={
  getAge:function(){
    console.log(this);
    return 22;
  }
}
console.log(obj.getAge());

arrow 函数不会创建自己的 this ,它仅使用 封闭 执行 上下文this 值。另一方面, arrow 函数使用父作用域的 this

Object.keys(jsonResult.jobs).forEach((key) => {
jobs.push(jsonResult.jobs[key].name);
   var job = jsonResult.jobs[key].name;
   console.log(job);
   this.getLastBuildAPI(job);   
});
Adelin
2018-01-12

您已将普通 函数 传递给 forEach ,从而更改了上下文。如果您想保留上下文,请使用箭头函数,或者,您可以创建一个新变量来保留对 this 的引用。

使用箭头函数:

Object.keys(jsonResult.jobs).forEach(key => {
    .....
    this.getLastBuildAPI(job); 
});

保留对 this 的引用:

var that = this;
Object.keys(jsonResult.jobs).forEach(function(key) {
     ....
    that.getLastBuildAPI(job); 
});
Titus
2018-01-12