创建具有源对象中所有方法的修改版本的对象
Create an object with modified versions of all methods in a source object
我想创建一个对象,它修改了源对象中所有方法的版本,但是我在使用for…in时遇到了麻烦。
如果这是源对象:
var raw = {};
raw.add = function(a,b){return a + b;}
raw.sub = function(a,b){return a - b;}
raw.neg = function(a){return -a;}
raw.sqrt = function(a){return Math.sqrt(a);}
如果我在字符串数组中重新创建属性列表,它会工作:
var mod2 = Object.create(raw);
var proplist = ["add", "sub", "neg", "sqrt"];
proplist.forEach(function(prop){
mod2[prop] = function(){
var arglist = [].slice.apply(arguments);
var out = [];
if(arglist.length == 1){
[].concat(arglist[0]).forEach(function(d){ out.push(raw[prop](d)); });
}
else if(arglist.length == 2){
[].concat(arglist[0]).forEach(function(d1){
[].concat(arglist[1]).forEach(function(d2){
out.push(raw[prop](d1,d2));
})
});
}
return out;
}
});
但是我尝试使用for. in不工作,新对象中的所有方法都将做"sqrt":
var modified = Object.create(raw);
for(prop in raw){
modified[prop] = function(){
var arglist = [].slice.apply(arguments);
var out = [];
if(arglist.length == 1){
[].concat(arglist[0]).forEach(function(d){ out.push(raw[prop](d)); });
}
else if(arglist.length == 2){
[].concat(arglist[0]).forEach(function(d1){
[].concat(arglist[1]).forEach(function(d2){
out.push(raw[prop](d1,d2));
})
});
}
return out;
}
}
自动遍历方法的最佳方法是什么?
您的第二个实现的问题是您在新方法中使用prop
(稍后将调用),但是创建prop
的for
循环已经运行到完成时该方法稍后被调用,因此prop
不再是正确的值(它将始终是最后一个属性)。我通过在IIFE(立即调用的函数表达式)中捕获prop
来解决这个问题,因此它将在每次通过for
循环时单独冻结。你的第一个实现没有这个问题,因为你在属性数组上使用.forEach()
,它使用一个回调函数,它为你自动捕获prop
的值到闭包中。
所以这是这些变化的结果,你的实现:
- 增加一个IIFE来冻结
prop
的值,以供新方法使用。 - 添加额外的检查,以确保我们复制的方法不是继承的,而是函数。
- 将
raw
初始化为一个普通对象,因为我没有看到任何理由在这里使用Object.create()
。
代码:
var raw = {};
raw.add = function(a,b){return a + b;}
raw.sub = function(a,b){return a - b;}
raw.neg = function(a){return -a;}
raw.sqrt = function(a){return Math.sqrt(a);}
var modified = {};
for (prop in raw) {
if (raw.hasOwnProperty(prop) && typeof raw[prop] === "function") {
(function (prop) {
modified[prop] = function () {
var arglist = [].slice.apply(arguments);
var out = [];
if (arglist.length == 1) {
[].concat(arglist[0]).forEach(function (d) {
out.push(raw[prop](d));
});
} else if (arglist.length == 2) {
[].concat(arglist[0]).forEach(function (d1) {
[].concat(arglist[1]).forEach(function (d2) {
out.push(raw[prop](d1, d2));
})
});
}
return out;
}
})(prop);
}
}
工作演示:http://jsfiddle.net/jfriend00/5LcLh/
<script>
var raw = {};
raw.add = function () { console.log('add default method'); }
raw.sub = function () { console.log('sub default method'); }
raw.neg = function () { console.log('neg default method'); }
raw.sqrt = function () { console.log('sqrt default method'); }
console.log('*****************');
console.log('before modifying');
console.log('*****************');
raw.add();
raw.sub();
raw.neg();
raw.sqrt();
var proplist = ["add", "sub", "neg", "sqrt"];
console.log('*****************');
console.log('after modifying');
console.log('*****************');
console.log('');
var modified = Object.create(raw);
for (prop in proplist) {
if (prop == 0)
console.log('rewriting methods and calling methods inside loop................');
modified[proplist[prop]] = function () { console.log(proplist[prop] + ' method modified, ' + proplist.length + ' argument passed') }
modified[proplist[prop]]();
}
console.log('');
console.log('trying call methods after loop is done................');
modified.add();
modified.sub();
modified.neg();
modified.sqrt();
console.log('...it is becaouse "prop" variable in loop holding last count number ' + prop);
</script>
感谢arnold.NET.JS的响应澄清了问题,我看到闭包是一种方法:
var raw = {};
raw.add = function(a,b){return a + b;}
raw.sub = function(a,b){return a - b;}
raw.neg = function(a){return -a;}
raw.sqrt = function(a){return Math.sqrt(a);}
var mod = Object.create(raw);
for(prop in raw){
mod[prop] = (function(){
var propname = prop;
function f(){
var arglist = [].slice.apply(arguments);
var out = [];
if(arglist.length == 1){
[].concat(arglist[0]).forEach(function(d){ out.push(raw[propname](d)); });
}
else if(arglist.length == 2){
[].concat(arglist[0]).forEach(function(d1){
[].concat(arglist[1]).forEach(function(d2){
out.push(raw[propname](d1,d2));
})
});
}
return out;
}
return f;
})();
}
相关文章:
- 对象文字方法上的Javascript绑定不起作用
- 如何在ajax中调用javascript对象的方法
- 解析带有嵌入式数组的JSON对象,方法
- 确定var是否是javascript中的elementFinder对象的方法是什么
- Javascript:对回调创建的对象执行方法
- 向通过ReST JSON调用生成的Angular Javascript对象添加方法
- 有没有办法在应用程序脚本中使用JavaScript为对象创建方法字典
- Rally SDK 2 标签选择器是否有必填字段?对象没有方法'getContextPath'
- 按键名调用 JSON 对象的方法有什么区别
- Box2dWeb中是否有方法将对象的位置.x输出到console.log()
- javascript构建对象.有什么区别和最好的方法
- 在反序列化JSON对象时,是否有方法将属性名称转换为小写?
- 这两种定义类/对象的方法有什么区别?
- 是否有可能发送我的对象与方法(函数)从服务器到客户端
- 有没有一种方法可以在不修改Object.prototype的情况下给所有对象一个方法?
- 这两种获取画布对象的方法有什么区别?
- 解析JSON字符串后是否有方法获得对象属性
- 检查对象是否有方法,而不实例化它
- 如果访问amazon s3对象,是否有方法调用lambda函数?
- 在Python中是否有向对象添加方法的惯用方法?