我有一个构造函数,最后应该返回几个方法。目前,我很难理解如何使用
中的值var info = JSON.parse(xhr.responseText);
方法中的,称为getNames。如果将这两种方法合而为一,则它可以工作,因此代码本身也可以工作,唯一的问题是传递变量。
function TestConstructor(url) {
var newObject = {};
this.newObject = newObject;
构造函数中的第一个方法:
newObject.load = function () {
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://notarealurl.com/104857.json");
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var info = JSON.parse(xhr.responseText);
return info;
}
};
xhr.send();
};
构造函数中的第二种方法:
newObject.getNames = function (info) {
var kommuner = info.elements;
var result = [];
for (i = 0; i < Object.keys(kommuner).length; i++) {
result.push(Object.keys(kommuner)[i]);
}
return result;
};
return newObject;
}
当我尝试
console.log(newObject.getNames(info));
我收到错误消息
Uncaught TypeError: Cannot read property 'elements' of undefined
at Object.TestConstructor.newObject.getNames
很抱歉,如果之前曾问过类似的问题,我看了几眼却不了解如何解决我的问题。我还尝试查看了回调函数,但是我很难理解它在我的情况下是如何工作的。任何帮助表示赞赏,谢谢:)
答案 0 :(得分:1)
我认为,您正在寻找的行为是将“信息”存储在构造的对象本地的变量中,然后从第二种方法访问该变量。因此,为什么不将var info = null;
放在构造函数中呢?然后,在解析数据后,将其分配给该变量(即删除var
)。而且,您不必使用参数info
,而只需使用该局部变量即可。
function TestConstructor(url) {
var newObject = {};
var info; // <-- local variable available to both functions.
this.newObject = newObject;
newObject.load = function () {
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://notarealurl.com/104857.json");
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
info = JSON.parse(xhr.responseText); // <-- assign result to local variable
}
};
xhr.send();
};
newObject.getNames = function() { // <-- no argument here
var kommuner = info.elements; // <-- instead, use local variable
var result = [];
for (i = 0; i < Object.keys(kommuner).length; i++) {
result.push(Object.keys(kommuner)[i]);
}
return result;
};
return newObject;
}
但是,这不是一个非常干净的解决方案。取而代之的是,正如SomePerformance建议的那样,您应该使用Promise模式异步提供数据,因为您目前尚不知道load
调用实际上何时完成。因此,当您调用info
时,getNames
甚至可能没有初始化。
基于承诺的解决方案可能如下所示:
function TestConstructor() {
var newObject = {},
info;
newObject.load = function () {
var p = new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://notarealurl.com/104857.json");
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) { // <-- call succeeded, parse result
info = JSON.parse(xhr.responseText); // <-- assign result to local variable
resolve(info); // <-- resolve promise with the result
} else {
reject(); // <-- call failed, reject the promise
}
}
};
xhr.send();
});
return p;
};
newObject.getNames = function() { // <-- no argument here
var kommuner = info.elements; // <-- instead, use local variable
var result = [];
for (i = 0; i < Object.keys(kommuner).length; i++) {
result.push(Object.keys(kommuner)[i]);
}
return result;
};
return newObject;
}
var myObj = new TestConstructor('');
myObj.load().then(function() {
var names = myObj.getNames();
// do something with the result.
console.log(names);
}).catch(function() {
// handle error graciously.
console.warn('Failed');
});