提问人:Bas Botman 提问时间:1/3/2023 更新时间:1/3/2023 访问量:56
为什么外部函数的属性继承给 JavaScript 函数的私有变量
why does the property of the external function inherit to the private variable of the javascript function
问:
尝试使用函数式编程创建具有外部函数的对象,以减少内存使用。
其功能是
//increment no of test cases
function incrNoOfTestCases(inputObj){
let hits = inputObj.hits;
console.log(`function says: ${hits}`)
return {...inputObj, hits: (hits || 0) + 1};
}
creator 函数是
const test = function(testDecription){
let state = {hits:0};
state.getState = ()=> testDecription;
state.incHits = () => state = incrNoOfTestCases(state);
state.getHits = () => state.hits || 0;
return state;
}
当我进行以下测试时,我可以通过为函数分配属性来更改命中。
test1.incHits().hits=10; //mutable!!
console.log(test1.getHits()); //gives 10
console.log(test1.incHits().hits); //gives function says: 10 and then 11
test1.hits=20; //immutable
console.log(test1.getHits()); //gives 10
我尝试了各种替代方案,最后想出了声明函数以增加创建器函数中的测试用例。我正在寻找一个解释为什么该属性是可变的,而不是工作案例。
在第一个版本中,该函数是
function incrNoOfTestCases(inputObj){
return {...inputObj, hits: (inputObj.hits || 0) + 1};
}
在这种情况下,我还希望 inputObj.hits 不会被 incrNoOfTestCases.hits 可变,但也不是。
似乎 JavaScript 在执行函数之前首先将 incrNoOfTestCases.hits 分配给 state。这是正确的吗?你能解释一下为什么吗?
答:
2赞
geoffrey
1/3/2023
#1
此代码没有任何功能。在函数式编程中,您不希望小逻辑单元独立处理其状态。那是OOP。如果更改值,则使用闭包与使用类相同。
这更实用,尽管它可能不像您想要的那样工作。
const Test = (description, hits = 0) => ({
getState: () => description,
incHits: () => Test(description, hits + 1),
getHits: () => hits
})
const test1 = Test('description')
const test2 = test1.incHits(); // incHits returns a new instance of Test
console.log(test2.getHits())
这本来可以做同样的事情
class Test {
constructor(description, hits = 0) {
this.description = description;
this.hits = hits;
}
static of (description) { return new Test(description) }
getState () { return this.description}
incHits () { return new Test(this.description, this.hits + 1); }
getHits () { return this.hits }
}
const test1 = Test.of('description');
const test2 = test1.incHits();
另一种方法
const Test = (description, hits = 0) => ({ description, hits, type: 'Test' });
export const getState = ({ description }) => description;
export const incHits = ({ description, hits }) => Test(description, hits + 1);
export const getHits = ({ hits }) => hits;
export const of = (description) => Test(description);
import * from './Test'
const test1 = Test.of('description');
const test2 = Test.incHits(test1);
评论
0赞
Bas Botman
1/5/2023
谢谢 Geoffrey,你让我进行了更多的研究,在你发表评论后再次深入研究 crockford.com/javascript/private.html 和他的书。我缺乏关于公共/私人和制作物品的方法的知识。最后,Douglas 使用一个返回对象的函数来创建一个对象(参见 JavaScript 的优点,第 5 章)。对我来说,它看起来很优雅,并且充分利用了 JavaScript。
0赞
geoffrey
1/5/2023
你学习这些东西是非常好的,但要意识到它已经有 20 年的历史了。类语法要简单得多。私人成员是自我记录的,在 Typescript 中,您甚至可以获得关键字(尽管它们只能保护您免受自己的伤害)。如果您不喜欢该关键字,请考虑使用静态方法(如“factory”函数,该函数将对象创建委托给构造函数,并仅传递参数。private
protected
new
Test.of
0赞
geoffrey
1/5/2023
在我的回答中列出的 3 种构造方式中,第一种是性能最差的,因为每次创建 的实例时都会创建新函数。它的可读性也不是很强,因为“方法”似乎有自由变量,它们是从闭包中获得的。一个类(在 JS 中)很明显,因为你必须提到,并且第 3 个示例中的函数采用参数。Test
this
0赞
geoffrey
1/5/2023
无论如何,请注意,在函数式编程中,对象不保持状态:它们只是数据袋。
下一个:树状结构中对父项的可变引用
评论
test1
test()
test1
test
incHints
hits
incrNoOfTestCases
incHits
test