javascript - 当我需要访问变量时,如何不使用 arguments.callee?
问题描述
假设我正在制作一个 JS 库,其中包含一些用于 DOM 操作的功能。我有一些添加到元素的函数,例如myElement.empty();
. 我希望NodeList
s 具有相同的功能(例如,从返回的对象querySelectorAll
)。要动态添加功能,我已经完成了以下操作(请注意,以下操作确实有效):
var funcs=["text","html","attr","remove","empty","css"];
var n=funcs.length;
while(~--n){
var f=function(){
var i,l=this.length;
for(i=0;i<l;i++){
this[i][ funcs[arguments.callee.n] ].apply(this[i], arguments);
}
return this;
};
f.n=n;
NodeList.prototype[funcs[n]]=f;
}
这行得通,但我听说这arguments.callee
在“严格”模式下不起作用。
有人说要给函数起个名字,但我不能,虽然我试过:
var funcs=["text","html","attr","remove","empty","css"];
var n=funcs.length;
while(~--n){
this[funcs[n]]=function(){
var i,l=this.length;
for(i=0;i<l;i++){
this[i][ funcs[name] ].apply(this[i], arguments);
// In the above it has 'name' which references the function name
}
return this;
};
NodeList.prototype[funcs[n]]=this[funcs[n]];
}
那没有用。 我能够使用 我决定不使用eval
. eval
,尽管它有效(通过放入n
字符串并从中制作函数)。如果我不得不使用其中一个,我认为这arguments.callee
可能比 更好。eval
如何在不使用建议的任何内容(例如arguments.callee
and eval
)的情况下使我的功能正常工作?
编辑以获取更多详细信息:
假设我定义了一个empty
函数(再次出于问题的目的,我们假设修改原型是可以的):
Element.prototype.empty=function(){
while(this.childNodes[0])
this.childNodes[0].remove();
};
这适用于一个元素。如果用户想做类似的事情怎么办:
document.querySelectorAll("button .myclass").empty();
所以我想制作一个脚本,NodeLists
为每个元素调用相应的函数动态创建函数,例如:
NodeList.prototype.empty=function(){
var i,l=this.length;
for(i=0;i<l;i++)
this[i].empty();
return this;
};
如果我想执行上述操作,我将需要创建许多功能非常相似的功能。所以我想写一些代码来动态地为NodeList
. 正如您可能在上面所读到的,我使用arguments.callee
(and eval
) 进行了操作,但我想使用标准的并且认为可以使用的东西。
我该怎么做?
如果您需要更多信息,请在评论中提问,我会尽快回复。
解决方案
不要使用那种奇怪的迭代风格,而是for … of
允许使用块范围变量的惯用循环:
const funcNames = ["text","html","attr","remove","empty","css"];
for (const name of funcNames) {
NodeList.prototype[name] = function(...args) {
for (let i=0; i<this.length; i++) {
this[i][name](...args);
}
return this;
};
}
没有理由访问当前函数或将名称存储在其.n
属性中,只需通过闭包访问它即可。
推荐阅读
- php - PHP - 新对象的默认函数参数
- jenkins - Jenkinsfile 代理“dockerfile”参数化“dir”参数
- javascript - EJS 替代 PHP die()
- android - 如何在 Android 11 中使用 NDK 从共享存储中打开文件
- c - MSP432 内存地址 0x40004c04
- java - 如何在 UDP 中实现循环缓冲区?
- javascript - JS - 如何删除使用谷歌地图 API 生成的所有路线
- azure - Cosmos db 更改提要触发器在函数进入睡眠状态后未触发
- hibernate - 当所有人都拥有该实体(没有EntityManager / Session)时,如何锁定()JPA / Hibernate实体?
- reactjs - React-Final-Form 隐藏字段值