我试图编写一个构造函数来生成用户的实例。user类的一个属性是用户业余爱好的数组。我希望我的构造函数有一个方法来生成一个字符串表示函数函数中提供的兴趣爱好数组。目标是创建一个语法上正确的句子,其中包含Person实例的兴趣爱好,因此如果interests = ['hiking', 'biking', 'skiing'],Person.bio()方法会发出警告,比如:This person's interests are: hiking, biking and skiing.,我试图解释一个未知长度的数组被传递给构造函数。
我并没有经常使用.reduce(),但从我所做的一些测试来看,它似乎能做我想做的事情。我只是在寻找任何批评如何使事情更可读性或表演性!
下面是构造函数的简化版本(为了清晰起见,缺少名称、年龄等)。
function Person(interests = []) {
this.interests = interests;
this.hobbiesSentence = interests.reduce((hobbyString, hobby, index, interests) => {
switch(index) {
case (interests.length - 1):
return hobbyString += `${hobby}.`
case (interests.length - 2):
return hobbyString += `${hobby} and `
default:
return hobbyString += `${hobby}, `
}
}, '');
this.bio = function () {
alert(`This person's interests are: ${this.hobbiesSentence}`)
};
}在编写这篇文章时,我可以看到一个使函数存在的例子,但除非调用bio()方法,否则不一定要创建/存储这个句子。还有其他想法吗?提前谢谢。
发布于 2019-08-08 01:10:53
字符串是不可变的,因此在循环中使用accumulator += stuffToAppend通常会影响性能。问题是,我们每次迭代都要创建一个新的字符串,从而导致一个应该是线性的操作的二次时间复杂度。事实证明,现代浏览器在很大程度上优化了这一点,使用内部数组来表示字符串部分,并使其比使用显式数组的速度更快,因此本文关注的是样式而不是性能。
首先,从语义的角度来看,reduce似乎是正确的函数,因为我们希望将兴趣数组归结为一个字符串。但是,由于避免字符串连接需要reduce中的中间数组,所以我们最好跳过中间数组,使用map和join。reduce可以替换为map或filter,这是非常常见的,后者更具体、更简洁。
开关语句也通常在JS中使用不多(但在C.中经常使用)。您可以将JS中的许多开关语句替换为一个对象(特别是当您在许多类似的函数之间进行选择时),或者至少使用一个if语句。无论如何,在这个例子中逗号和" and“的性质都会让它变得有点尴尬,所以似乎没有任何明显的胜利。
此外,这个“美化”列表的例程是通用的,可以移动到一个单独的函数中,以保持Person的干净。
顺便说一句,与其在“兴趣”、“爱好”和“生物”之间切换,不如选一个词,并始终坚持下去。
这是我的尝试。这看上去有点抽象,但在JS中,避免条件/切换内容和避免循环(这是reduce的思想)是很典型的。如果您更喜欢一种更传统的方法,请将joins数组替换为if语句并进行索引,我仍然赞同它。
const prettyList = (a, sep=", ", endSep=[" and ", "."]) =>
a.map((e, i) => e + (endSep[endSep.length-a.length+i] || sep)).join("")
;
const Person = function (interests=[]) {
this.interests = interests;
this.interestsSentence = prettyList(interests);
this.interestsStr = () =>
"This person's interests are: " + this.interestsSentence
;
};
const interests = ["foo", "bar", "baz", "quux"];
for (let i = 1; i <= 4; i++) {
console.log(new Person(interests.slice(0, i)).interestsStr());
}现在,这个函数是可重用的,我们可以不费太大力气就可以改变它的行为:
const prettyList = (a, sep=", ", endSep=[" and ", "."]) =>
a.map((e, i) => e + (endSep[endSep.length-a.length+i] || sep)).join("")
;
const activities = ["biking", "running", "walking", "skipping", "driving"];
console.log("I love", prettyList(activities, "; ", [", sometimes ", " but not ", "!"]));
console.log("I love", prettyList(activities, " and ", [" while ", " :-o"]));https://codereview.stackexchange.com/questions/225743
复制相似问题