我正在为我的新网站项目使用JS路由器。路由器接受一个对象:Key是URL地址,Value是一个在到达地址时被调用的函数。
随着页面数量和子页面越来越大,它变得越来越混乱,特别是考虑到不同的页面需要调用不同的初始化函数(initAccordion
或initDataTables
等等)。 / p>
为了保持整洁我想到了创建一个对象数组,这些对象将保存页面名称和加载页面后需要调用的init函数。但是,我使用的解决方案使用eval
:
function initFoo() {
console.log("initFoo says hi");
}
function initBar() {
console.log("initBar says hi");
}
var pages = [
{
name: "home",
init: ["initFoo", "initBar"]
},
{
name: "people",
init: ["initBar"]
}
];
var routerPaths = {};
for (var page in pages) {
var url = pages[page].name;
var init = pages[page].init;
// construct the string for eval()
var objStr = "routerPaths['" + url + "'] = function() {";
for(var item in init) {
objStr += init[item] + "();";
}
objStr += "};";
eval(objStr);
}
routerPaths.home(); // as expected: initFoo says hi initBar says hi
routerPaths.people(); // as expected: initBar says hi
这一切都很好,但有没有办法让pages.init
数组没有引号而对象创建者不使用eval
?因此,值看起来像init: [initFoo, initBar]
。
所以我的问题确实是:有没有一种方法可以创建新的routerPaths
对象而无需构造字符串然后在其上运行eval
?我应该坚持我拥有的东西吗?
请注意,routerPaths.home
,routerPaths.people
必须是调用pages.init
中函数的函数。
答案 0 :(得分:1)
不需要通过字符串名称引用函数。只需像任何其他变量一样使用函数名称。 var pages = [ { 名称:" home", init:[initFoo,initBar] }, { 名字:"人物", init:[initBar] } ];
并将您的init
存根编写为普通的闭包(注意:在循环中使用let
而不是var
是必须的。)
var routerPaths = {};
for (var page of pages) {
let init = page.init;
routerPaths[page.name] = function() {
init.forEach(function(fn) { fn() })
}
}
如果您无法使用ES6 for...of
和let
,请将其替换为`forEach:
pages.forEach(function(page) {
var init = page.init;
routerPaths[page.name] = function() {
init.forEach(function(fn) { fn() })
}
})
答案 1 :(得分:0)
const initFoo=()=>{
console.log("initFoo says hi");
}
const initBar=()=> {
console.log("initBar says hi");
}
let pages = [
{
name: "home",
init: [initFoo, initBar]
},
{
name: "people",
init: [initBar]
}
];
let routerPaths = {
};
for (let page in pages) {
let url = pages[page].name;
let init = pages[page].init;
Object.defineProperty( routerPaths , url , {
value: ()=>{
for(var item in init) {
init[item]();
}
},
enumerable: true, // if enumerable is true then only you can see the people,home properties if you console.log
//if enumerable set to false you can not see the the property but you can still call routerPaths.people and it just works fine
});
}
console.log(routerPaths);
routerPaths.home(); // as expected: initFoo says hi initBar says hi
routerPaths.people(); // as expected: initBar says hi