【问题标题】:js function optimizationjs函数优化
【发布时间】:2012-10-11 12:33:40
【问题描述】:

我发现自己经常从 JavaScript 中所谓的名称值列表中解析值。

我使用了一个自制的函数,它做得很好,但是我决定尝试原型属性。它似乎有效,但是我发现第二个函数“nvlSet”有点“丑陋”。

你认为是吗?如果是的话,你认为它如何变成一种更“优雅”的工作方式。

if(!String.prototype.nvlGet) {
    String.prototype.nvlGet = function(nme,def){
        return((rem0=new RegExp('(\\b|,)' + nme + '=([^\\b][^,]*)').exec(this)) ? rem0[2] : def);
    }
}
if(!String.prototype.nvlSet) {
    String.prototype.nvlSet = function(nme,val){
        var re0=new RegExp('(\\b' + nme + '=[^\\b][^,]*)');
        if(re0.test(this)) return(this.replace(re0,nme + "=" + val));
        re0.compile('(,' + nme + '=[^\\b][^,]*)');
        return(this.replace(re0,',' + nme + "=" + val));
    }
}

var lst='firstName=John,lastName=Smith,department=Sales';
alert(lst.nvlGet('firstName')); // John
alert(lst.nvlGet('surName','none')); // none
lst=lst.nvlSet('department','Research');
alert(lst.nvlGet('department','unknown')); // Research
alert(lst); // firstName=John,lastName=Smith,department=Research

另外,我想避免像这里这样的“双重分配”:

lst=lst.nvlSet('department','Research');

到这样的事情:

lst.nvlSet('department','Research');

但是我找不到办法。

【问题讨论】:

    标签: javascript regex optimization nvl


    【解决方案1】:

    我建议将 nvls 序列化和反序列化为对象。一个相当简单的例子是:

    function deserialize(nvl) {
      var re = /(\w+)=(\w+)/g, matches, props = {};
      while (matches = re.exec(nvl)) {
        props[matches[1]] = matches[2];
      }
      return props;
    }
    
    function serialize(props) {
      var prop, nvl = [];
      for (prop in props) {
        if (props.hasOwnProperty(prop)) {
          nvl.push(prop + '=' + props[prop]);
        }
      }
      return nvl.join(',');
    }
    

    现在你的例子变成了:

    var props = deserialize('firstName=John,lastName=Smith,department=Sales');
    alert(props.firstName); // John
    alert(props.surName); // undefined
    props.department = 'Research';
    alert(props.department); // Research
    alert(serialize(props)); // firstName=John,lastName=Smith,department=Research
    

    【讨论】:

    • 这个看起来又好又快,但是我们有一堆 Svr sde 脚本以这种格式(纯文本 nvl)返回数据。返回的数据在某些情况下必须每秒解析很多次。所以这就是为什么我在字符串上选择直接正则表达式,但这绝对是优雅的,并且会在某些情况下使用。谢谢!
    【解决方案2】:

    字符串在 javascript 中是不可变的。您永远无法更改当前字符串对象的内容。这就是为什么所有对字符串进行操作的字符串方法都会返回一个新的字符串对象。所以,你想要的结构:

    lst.nvlSet('department','Research');
    

    你希望它修改当前字符串对象的地方无法完成。

    您可以创建自己的常规对象来保存状态,然后拥有获取或设置该状态的方法,如下所示:

    function nvl(str) {
        this.data = {};
        if (str) {
            this.data = this.parse(str);
        }
    }
    
    nvl.prototype = {
        parse: function(str) {
            var result = {}, pieces;
            var items = str.split(",");
            for (var i = 0; i < items.length; i++) {
                pieces = items[i].split("=");
                result[pieces[0]] = pieces[1];
            }
            return(result);
        },
        get: function(key, defaultVal) {
            var val = this.data[key];
            if (val === undefined) {
                val = defaultVal;
            }
            return(val);
        },
        set: function(key, value) {
            this.data[key] = value;
        },
        serialize: function() {
            var arr = [];
            for (var i in this.data) {
                if (this.data.hasOwnProperty(i)) {
                    arr.push(i + "=" + this.data[i]);
                }
            }
            return(arr.join(","));
        }
    };
    

    工作示例:http://jsfiddle.net/jfriend00/3urJF/

    【讨论】:

    • +1,OP 应该使用构造函数并将 nvlSetnvlSet 方法放在其原型上。
    • 我今天学到了一些关于 JS 的知识,你明白了我所说的“双重分配”的意思,感谢你的评论,我知道这是不可能的。我会将您的完整课程用于其他每秒不会执行多次的类似场景。
    【解决方案3】:

    这个怎么样:

    //add nvl as a method to String prototype
    String.prototype.nvl = function(){
    
        //new prototype for the dictionary object that gets returned
        var proto = {
    
            //convert the object literal back into a nvl
            toNvl: function(){
    
                var str = [];
                for(var i in this){
    
                    if( this.hasOwnProperty(i) ){
                        str.push(i+'='+this[i]);
                    }
    
                }
    
                //return str.join(',');
                return str.join(',');
            }
        },
        //set the prototype of the object literal to our own
        dict = Object.create(proto);
    
        //convert the string into an object literal
        keys = this.split(',');
    
        keys.forEach(function(val, index, arr){
            arr = val.split('=');
            dict[arr[0]] = arr[1];
        });
    
        return dict;
    }
    
    
    var pop = 'color=blue,num=234'.nvl(); //convert the string to an object
    
    pop.color = 'red'; //access object properties normally.
    
    pop = pop.toNvl(); //convert back to nvl. reassignment is unfortunately necessary
    

    【讨论】:

    • 我忘了提醒,如果名称不存在,则必须附加。
    • 只需像设置任何对象一样设置属性。 pop.whatever = "随便"
    猜你喜欢
    • 1970-01-01
    • 2021-02-13
    • 2018-03-21
    • 2021-09-12
    • 2016-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多