1

我发现我自己经常从 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');

但是我找不到办法做到这一点。

4

3 回答 3

2

我建议将 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
于 2012-10-10T23:43:50.670 回答
1

字符串在 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/

于 2012-10-10T23:59:02.213 回答
0

这个怎么样:

//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
于 2012-10-11T04:33:40.253 回答