问题
I have a JavaScript class like this:
Dog = (function() {
var name;
function setName(_name) {
name = _name;
}
return {
setName: setName,
name: name
};
})();
When I run:
Dog.setName('Hero');
Dog.name
is always undefined.
I am certainly missing something about JS scoping, but what?
回答1:
You are returning an object where name
property has a value of name
at that point in time (which is undefined). The name
property of the returned object is not somehow dynamically updated when the name
variable inside the IIFE is updated.
There are many ways to handle what you appear to be wanting to do. Here's one:
Dog = (function() {
var name;
function setName(_name) {
name = _name;
}
return Object.defineProperties({}, {
setName: { value: setName },
name: { get: function() { return name; } }
});
})();
This keeps name
as a private variable, which can only be set via setName
, but provides a getter property for obtaining its value.
The alternative proposed in another answer is equivalent, just a different way of writing it:
return {
setName: function(n) { name = n; },
get name: function() { return name; }
};
Minor point, but in this particular context you don't need parentheses around your IIFE:
Dog = function() { }();
will work fine.
回答2:
This happens because you assume that setting name
in the object retains a reference to the original name
variable. Instead, you want to assign it to the current object (which, you might as well ignore the private variable altogether).
Dog = {
name: '',
setName: function(n) {
this.name = n;
}
};
However, if you want to keep name
private then you create a getter for it instead.
var Dog = (function() {
var name;
return {
setName: function(n) {
name = n;
},
get name: function() {
return name;
}
};
})();
回答3:
The easy way to fix this is:
Dog = (function() {
var dog = {
setName: setName,
name: name
};
function setName(_name) {
dog.name = _name;
}
return dog;
}
In your code, you were setting the wrong name
variable.
var name;
function setName(_name) {
name = _name;
}
In this function, setName is setting the internal variable name
and not the property name
. In JavaScript, strings are immutable, so when you change it, it creates a new string, and doesn't update the existing one.
回答4:
This might be a better pattern for you. You're using the very old ES3 style constructor.
(function(exports) {
function Dog(name) {
this.name = name;
}
Dog.prototype.speak = function() {
return "woof";
};
// other functions ...
exports.Dog = Dog;
})(window);
var d = new Dog('Hero');
console.log(d.name); // "Hero"
You might want to look into ES6 classes too
class Dog {
constructor(name) {
this.name = name;
}
}
let d = new Dog('Hero');
console.log(d.name); // "Hero"
回答5:
Sounds like you want to make a constructor... Check this sample:
function Dog(prop) {
this.name = prop.name;
this.color = prop.color;
}
var myDog = new Dog({
name:'Sam',
color: 'brown'
});
alert()
console.log('my dog\'s name is: '+myDog.name);
console.log('my dog\'s color is: '+myDog.color);
you can try it here: http://jsfiddle.net/leojavier/ahs16jos/
I hope this helps man...
回答6:
Use the 'this' keyword.
Dog = (function() {
var name;
function setName(_name) {
this.name = _name;
}
return {
setName: setName,
name: name
};
})();
Dog.setName('Hero');
alert(Dog.name);
来源:https://stackoverflow.com/questions/32258237/javascript-variable-inside-class-is-always-undefined