当前位置: 动力学知识库 > 问答 > 编程问答 >

javascript - Variable loses value when referenced a second time

问题描述:

I have some Ajax that gets info from a database and stores it in an array called targetVocab. This info is used to set the value of vocab when setVocab() is called. This works fine the first time, but when the play again button is hit and setVocab is called a second time, it doesn't work. The second time it appears that targetVocab is empty. This is my simplified script...

var targetVocab;

var vocab;

var request = new goog.net.XhrIo();

goog.events.listen(request, "complete", function(){

if (request.isSuccess()) {

response = request.getResponseJson();

targetVocab = response['targetVocab'];

setVocab(targetVocab);

}

});

request.send("load_vocab.php");

var setVocab = function(targetVocab) {

vocab = targetVocab;

}

var getVocab = function() {

return vocab;

}

goog.events.listen(playAgainButton, ['mousedown', 'touchstart'], function(e) {

getVocab();

});

UPDATE:

I've come to realize that whatever I do to vocab is similarly applied to targetVocab. My original idea was that I could splice elements from vocab throughout the app and then reset vocab to it's original state by setting it again to targetVocab. Is there some way to set vocab equal to targetVocab without the two remaining connected in this way?

网友答案:

I think your problem is caused by setting vocab to targetVocab. In JavaScript when you set a new variable to the value of an object variable then both variables will point to the same object:

var a = [{a:0}];
var b = a
a.splice(0,1);
console.log(b);//=[] empty array

What you're looking for is making a clone of your object, I could find goog.object.clone and goog.object.unsafeClone in the closure library.

clone will only do a shallow copy so if your array would contain immutable objects or primative types you can use clone but if you are going to do something with the cloned array as in the following example you'll need unsafeClone:

var a = [{a:0}];
var b = goog.object.clone(a);
a[0].a=22;
console.log(b[0]);//=22
// b isn't even an array here so I'm not sure what clone does
//   but it doesn't do much
console.log(b instanceof Array);//false

If you're never going to change the values of the array's items and never call functions that'll change the items internal values (like copiedarray[0].changevalue(); or copiedarray[index].someval=newval;) then you can copy a reference to the items in a new array:

var a = [{a:0}];
var b = a.concat([]);
// can't do a[0].a=newValue or it'll permanently change
a.splice(0,1);
console.log(b[0]);//=0

UnsafeClone will fully clone the object but you'll run the risk of starting a never ending loop when a property of any object (property) references itself:

var a = [{a:0}];
var b = goog.object.unsafeClone(a);
a[0].a=22;
console.log(b[0]);//=0
console.log(b instanceof Array);//true

In your case; since the object to be copied comes from a JSON string there won't be circular references but there may be a better way to do it since unsafeClone may be slower than goog.json.parse

...
if (request.isSuccess()) {
    targetVocab = request.getResponseText();
    setVocab();
}
...
var setVocab = function() {
  vocab = goog.json.parse(targetVocab)['targetVocab'];
}    
...
网友答案:

You need to define the function setVocab differently.

A second thing I just realized: you should write 2 functions one set function and one GET function this waay the will not splice anymore.

e.g.

 function setVocab(targetVocab){
    vocab = targetVocab;       
}

This way you ensure that you really pass it the targetVocab as a variable. And now the GET function accordingly:

 function getVocab(){
    return vocab;
}

OR put it in one (not recommended)

function setVocab(targetVocab){
    if(targetVocab!=""){
     vocab = targetVocab;
    }else{
     return vocab;
    }
}

Now depending on what you have implemented call

goog.events.listen(playAgainButton, ['mousedown', 'touchstart'], function(e) {
getVocab();

});

or if you implemented the "not recommended" code then use this

goog.events.listen(playAgainButton, ['mousedown', 'touchstart'], function(e) {
setVocab("");

});

and

goog.events.listen(request, "complete", function(){

if (request.isSuccess()) {
    response = request.getResponseJson();
    targetVocab = response['targetVocab'];
    setVocab(targetVocab); //chaged here
}

});

分享给朋友:
您可能感兴趣的文章:
随机阅读: