Changing the RegExp flags

后端 未结 4 1977
长发绾君心
长发绾君心 2020-12-16 12:57

So basically I wrote myself this function so as to be able to count the number of occurances of a Substring in a String:

String.prototype.numberOf = function         


        
相关标签:
4条回答
  • 2020-12-16 13:40

    First, your current code does not work correctly when needle is a regex which does not match. i.e. The following line:

    return this.match(needle).length;
    

    The match method returns null when there is no match. A JavaScript error is then generated when the length property of null is (unsuccessfully) accessed. This is easily fixed like so:

    var m = this.match(needle);
    return m ? m.length : 0;
    

    Now to the problem at hand. You are correct when you say that global, ignoreCase and multiline are read only properties. The only option is to create a new RegExp. This is easily done since the regex source string is stored in the re.source property. Here is a tested modified version of your function which corrects the problem above and creates a new RegExp object when needle does not already have its global flag set:

    String.prototype.numberOf = function(needle) {
        var num = 0,
        lastIndex = 0;
        if (typeof needle === "string" || needle instanceof String) {
            while((lastIndex = this.indexOf(needle, lastIndex) + 1) > 0)
                {num++;} return num;
        } else if(needle instanceof RegExp) {
            if (!needle.global) {
                // If global flag not set, create new one.
                var flags = "g";
                if (needle.ignoreCase) flags += "i";
                if (needle.multiline) flags += "m";
                needle = RegExp(needle.source, flags);
            }
            var m = this.match(needle);
            return m ? m.length : 0;
        }
        return 0;
    };
    
    0 讨论(0)
  • 2020-12-16 13:53

    There isn't much you can do but I highly recommend you avoid using eval. You can extend the RegExp prototype to help you out.

    RegExp.prototype.flags = function () {
        return (this.ignoreCase ? "i" : "")
            + (this.multiline ? "m" : "")
            + (this.global ? "g" : "");
    };
    
    var reg1 = /AAA/i;
    var reg2 = new RegExp(reg1.source, reg1.flags() + 'g');
    
    0 讨论(0)
  • 2020-12-16 13:54
    var globalRegex = new RegExp(needle.source, "g");
    

    Live Demo EDIT: The m was only for the sake of demonstrating that you can set multiple modifiers

    var regex = /find/;
    var other = new RegExp(regex.source, "gm");
    alert(other.global);
    alert(other.multiline);
    
    0 讨论(0)
  • 2020-12-16 13:58
    r = new Regexp(r.source, r.flags + (r.global ? "" : "g"));
    
    0 讨论(0)
提交回复
热议问题