类中的JavaScript变量始终未定义
我有这样一个JavaScript类:类中的JavaScript变量始终未定义,javascript,javascript-objects,Javascript,Javascript Objects,我有这样一个JavaScript类: Dog = (function() { var name; function setName(_name) { name = _name; } return { setName: setName, name: name }; })(); 当我跑步时: Dog.setName('Hero'); Dog.name始终未定义 我当然遗漏了一些关于JS作用域的内容,但是什
Dog = (function() {
var name;
function setName(_name) {
name = _name;
}
return {
setName: setName,
name: name
};
})();
当我跑步时:
Dog.setName('Hero');
Dog.name
始终未定义
我当然遗漏了一些关于JS作用域的内容,但是什么呢?这可能是一种更好的模式。您正在使用非常旧的ES3样式构造函数
(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"
你可能也想看看ES6课程
class Dog {
constructor(name) {
this.name = name;
}
}
let d = new Dog('Hero');
console.log(d.name); // "Hero"
您正在返回一个对象,其中
name
属性在该时间点的值为name
(未定义)。当IIFE中的name
变量更新时,返回对象的name
属性不会以某种方式动态更新
有很多方法可以处理你看起来想要做的事情。这里有一个:
Dog = (function() {
var name;
function setName(_name) {
name = _name;
}
return Object.defineProperties({}, {
setName: { value: setName },
name: { get: function() { return name; } }
});
})();
这使name
保持为私有变量,只能通过setName
设置,但提供了获取其值的getter属性
另一个答案中提出的备选方案是等效的,只是书写方式不同:
return {
setName: function(n) { name = n; },
get name: function() { return name; }
};
次要的一点,但在这种特殊情况下,你的生活不需要括号:
Dog = function() { }();
会很好的 使用“this”关键字
Dog = (function() {
var name;
function setName(_name) {
this.name = _name;
}
return {
setName: setName,
name: name
};
})();
Dog.setName('Hero');
alert(Dog.name);
这是因为您假定对象中的设置
name
保留了对原始name
变量的引用。相反,您希望将其分配给当前对象(您也可以完全忽略私有变量)
但是,如果您想保持name
私有,那么您可以为其创建一个getter
var Dog = (function() {
var name;
return {
setName: function(n) {
name = n;
},
get name: function() {
return name;
}
};
})();
解决此问题的简单方法是:
Dog = (function() {
var dog = {
setName: setName,
name: name
};
function setName(_name) {
dog.name = _name;
}
return dog;
}
在代码中,您设置了错误的name
变量
变量名
function setName(_name) {
name = _name;
}
在此函数中,setName设置的是内部变量
name
,而不是属性name
。在JavaScript中,字符串是不可变的,因此当您更改它时,它会创建一个新的字符串,而不会更新现有的字符串。听起来像是要创建一个构造函数。。。检查此示例:
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);
您可以在这里尝试:
我希望这有助于人类……如何定义
Dog.setName
更不用说函数了?如果不抛出类型错误
,该如何执行?对,我更改了一些函数名,等等,但忘了将其添加到返回块中。更新了答案。谢谢。对downvoter:你能解释一下这个问题的错误吗?这样我就可以从错误中吸取教训了?有没有办法使用Singleton?所以我在整个应用程序中都有一个Dog对象,没有创建“new”。这应该是你最初的问题。你可以找到无数关于如何使用JavaScript实现单例的例子。当然,但从他编写的setName
函数来看,他似乎对保持name
私有感兴趣。我也认为这就是问题所在。但是我对JS的了解还不足以解决这个问题。谢谢,这非常有效。你能多告诉我一点我的课吗?走这条路对吗?有没有更好的方法用闭包和私有变量实现类?是的,有。然而,当我调试脚本时,我可以清楚地看到setName在运行后设置了正确的“name”变量。我可以看出狗的“名字”设置正确。但我不能让它超出它的范围。那不是提升,那是关闭。提升是指在函数中声明的变量,它们都在函数级别具有作用域。你的函数是函数内部的函数,内部函数可以引用外部函数的变量。是的,你说内部函数可以引用外部函数的变量,但在回答中你说内部函数正在设置内部变量名。那么内部函数如何引用外部函数的变量呢?(关于我的班级)。我还认为你所描述的问题是起重问题。谢谢。对不起,不行。它无法设置此。名称,抛出一个错误。在测试的每个浏览器中对我都有效。更新了完整示例的答案。
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);