1

根据上一个问题的答案更新我的代码后,我想出了以下解决方案:

var Coder = (function() {
    var controlWords = [
            ['ONE','OO'],
            ['TWO','TT'],
            ['THREE','RR'],
          //['...','..'],
            ['END','NN']
        ],
        map = {
            '0':' ', '1':'_', '2':',',
            '3':'.', '4':'?', '5':'!',
            '6':'\'','7':'"', '8':'(',
            '9':')', 'a':'o', 'b':'d',
            'c':'a', 'd':'e', 'e':'p',
            'f':'i', 'g':'f', 'h':'v',
            'i':'u', 'j':'l', 'k':'m',
            'l':'y', 'm':'q', 'n':'x',
            'o':'b', 'p':'j', 'q':'t',
            'r':'n', 's':'z', 't':'w',
            'u':'k', 'v':'h', 'w':'s',
            'x':'c', 'y':'r', 'z':'g'
        },
        reverseMap = (function() {
            var j, tmp = {};
            for (j in map){
                if (Object.prototype.hasOwnProperty.call(map, j))
                    tmp[map[j]] = j;
            }
            return tmp;
        })(),
        value, i,
        encode = function(data) {
            var input = (typeof data == 'string' ? data : '');
console.log('Input to encode: '+input);
            for (i = 0; i < controlWords.length; i++) {
                value = new RegExp(controlWords[i][0],'g');
                input = input.replace(value,controlWords[i][1]);
            }
console.log('Encode step 1: '+input);
            input = input.replace(/./g, function(c){
                return reverseMap[c]
                    || reverseMap[c.toLowerCase()].toUpperCase();
            });
console.log('Encoding output: '+input);
            return {length: input.length, data: input};
        },
        decode = function(data) {
            var input = (typeof data == 'string' ? data : '');
console.log('Input to decode: '+input);
            input = input.replace(/./g, function(c){
                return map[c]
                    || map[c.toLowerCase()].toUpperCase();
            });
console.log('Decode step 1: '+input);
            for (i = 0; i < controlWords.length; i++) {
                value = new RegExp(controlWords[i][1],'g');
                input = input.replace(value,controlWords[i][0]);
            }
console.log('Decoding output: '+input);
            return {length: input.length, data: input};
        };
    return {encode: encode, decode: decode};
})();
var str = 'ONE Hello, TWO JavaScript THREE World! END',
    enc = Coder.encode(str).data,
    dec = Coder.decode(enc).data;

如您所见,有很多完全或几乎重复的代码。唯一有意义的区别是两种转换发生的顺序,是否map使用reverseMap,以及每个控制字数组的哪个索引用作正则表达式,哪个用作替换值。

为了遵守将重复代码包装在子函数中并调用该函数的概念,我做了以下尝试。它将两个转换定义为内部函数,然后根据type参数的值决定其余的。

var Coder = (function() {
    var controlWords = [ /* same */ ],
        map = { /* same */ },
        reverseMap = /* same */,
        code = function(data, type) {
            var input = (typeof data == 'string' ? data : ''),
                mapping, x, y, value, i,
                transform = function() {
                    return input.replace(/./g, function(c){
                        return mapping[c]
                            || mapping[c.toLowerCase()].toUpperCase();
                    });
                },
                replace = function() {
                    for (i = 0; i < controlWords.length; i++) {
                        value = new RegExp(controlWords[i][x],'g');
                        input = input.replace(value,controlWords[i][y]);
                    }
                    return input;
                };
            if (type == 'decode') {
                mapping = map;
                x = 1;
                y = 0;
                input = transform();
                input = replace();
            } else if (type == 'encode') {
                mapping = reverseMap;
                x = 0;
                y = 1;
                input = replace();
                input = transform();
            } else {
                throw new Error('Invalid type argument!');
            }
            return {data: input, length: input.length};
        };
    return {code: code};
})();
var str = 'ONE Hello, TWO JavaScript THREE World! END',
    enc = Coder.code(str, 'encode').data,
    dec = Coder.code(enc, 'decode').data;

但是,您可能会注意到此代码实际上更长。如果我想添加比“编码”和“解码”更多的类型(不打算),它仍然更容易扩展。但目前效率较低?

然后我回到具有两个功能的版本(以避免传递和检查“类型”):

var Coder = (function() {
    var controlWords = [ /* same */ ],
        map = { /* same */ },
        reverseMap = { /* same */ },
        input, mapping, x, y, value, i,
        transform = function() {
            return input.replace(/./g, function(c){
                return mapping[c]
                    || mapping[c.toLowerCase()].toUpperCase();
            });
        },
        replace = function() {
            for (i = 0; i < controlWords.length; i++) {
                value = new RegExp(controlWords[i][x],'g');
                input = input.replace(value,controlWords[i][y]);
            }
            return input;
        },
        encode = function(data) {
            input = (typeof data == 'string' ? data : '');
            mapping = reverseMap;
            x = 0;
            y = 1;
            input = replace();
            input = transform();
            return {length: input.length, data: input};
        },
        decode = function(data) {
            input = (typeof data == 'string' ? data : '');
            mapping = map;
            x = 1;
            y = 0;
            input = transform();
            input = replace();
            return {length: input.length, data: input};
        };
    return {encode: encode, decode: decode};
})();
// Call methods same as first example

这么长的帖子基本上要问,当它并没有真正帮助代码长度并且没有计划扩展代码或将其作为公共项目发布时,哪个更好,重复代码或额外的功能/检查?其中哪一个是最优雅的解决方案,还是有更好的解决方案?

编辑

我想到的一般清理它的一种方法是删除 , 和 的变量声明,mapping并将它们作为参数传递给and 。这将产生xyreplacetransform

decode = function(data) {
    var input = (typeof data == 'string' ? data : '');
    input = transform(map);
    input = replace(1,0);
    return {length: input.length, data: input};
}
4

0 回答 0