创建具有源对象中所有方法的修改版本的对象

Create an object with modified versions of all methods in a source object

本文关键字:对象 有方法 修改 版本 创建      更新时间:2023-09-26

我想创建一个对象,它修改了源对象中所有方法的版本,但是我在使用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(稍后将调用),但是创建propfor循环已经运行到完成时该方法稍后被调用,因此prop不再是正确的值(它将始终是最后一个属性)。我通过在IIFE(立即调用的函数表达式)中捕获prop来解决这个问题,因此它将在每次通过for循环时单独冻结。你的第一个实现没有这个问题,因为你在属性数组上使用.forEach(),它使用一个回调函数,它为你自动捕获prop的值到闭包中。


所以这是这些变化的结果,你的实现:

  1. 增加一个IIFE来冻结prop的值,以供新方法使用。
  2. 添加额外的检查,以确保我们复制的方法不是继承的,而是函数。
  3. 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;
    })();
}