zhangxinxu/quiz

JS基础测试30

Opened this issue · 32 comments

本期题目如下,字符长度判断。

其中,题2-题4需求是叠加的,也就是题4的判断需要同时满足题2和题3的需求。

大家提交回答的时候,注意缩进距离,起始位置从左边缘开始;另外,github自带代码高亮,所以请使用下面示意的格式。

```js
// 你的JS代码写在这里
 ```

其它:

  1. 首位答题者可获得额外2积分和直播翻牌机会;
  2. 本次答疑直播为4月6日(周六)上午10:00;

通过正则去处理原始的content,然后比较字符串长度和140的大小

// 第一题
function getLength1(content) {
  return content.length > 140
}
// 第二题
// 将多个空白符合并为一个
function getLength2(content) {
  let str = content.trim().replace(/[\s]{2,}/g,' ')
  return str.length > 140
}
// 第三题
function getLength3(content) {
  let str = content.trim().replace(/[\s]{2,}/g,' ')
  return Math.ceil(str.length / 2) > 140
}
// 第四题
// 考虑url地址会常规输入的值界限为一个空白符
function getLength4(content) {
  // 匹配url在文本中间的
  let regx1 = /(http|https):\/\/([\w-]+\.)+[\w-]+([\w-.\?%&=]*)*\s/g
  // 匹配url在文本结尾 由于忽略了空白符所以我单独拿出来
  let regx2 = /(http|https):\/\/([\w-]+\.)+[\w-]+([\w-.\?%&=]*)*$/
  // 这里 11个x 最后一个用来弥补空格
  let str = content.trim()
                  .replace(/[\s]{2,}/,' ')
                  .replace(regx1, 'xxxxxxxxxxx')
                  .replace(regx2, 'xxxxxxxxxx')
  return Math.ceil(str.length / 2) > 140
}

const content = '   123 http://www.baidu.com?a=3&b=4   大家提交回答的时候,注意缩进距离,起始位置从左边缘开始;另外,github自带代码高亮,所以请使用下面示意的格式cccccccccccccccccccccccccccccccccc。    https://www.github.com'
console.log(getLength1(content))
console.log(getLength2(content))
console.log(getLength3(content))
console.log(getLength4(content))

没有什么字符串处理是用一个正则表达式解决不了的,如果有,那就用两个,事实上我用了四个。

DEMO 更精彩 (已封装,并提供测试用例)


第 1 题

这是送分题吗?

content.length > 140;

第 2 题

使用正则将所有连续空格、换行替换为1个

content.trim()  // 移除两端空格
  .replace(/[\r\n]+/g, '\n')  // 连续换行合并为 1 个
  .replace(/[ ]+/g, ' ')  // 内容中的连续空格合并成 1 个
  > 140;

第 3 题

原理:将内容按 2 个 ASCⅡ 字符作为切割点划分数组,累加统计数组项里面的字符数,再加上数组长度 - 1 的值,得到最终字数

var arr = content.trim()
  .replace(/[\r\n]+/g, '\n')
  .replace(/[ ]+/g, ' ')
  .split(/[\x00-\xff]{2}?/g);  // ASCⅡ 码范围(惰性匹配)
var len = arr.length - 1 + arr.reduce(function(total, cur) {
  return total += cur.length	
}, 0);
len > 140;

第 4 题

先按题 2 处理,然后使用正则匹配网址并替换为 10 个占位字符,最后按题 3 处理,统计最后字数

function fixASC2CharsNum(str) {
  var arr = str.split(/[\x00-\xff]{2}?/g);

  return arr.length - 1 +
    arr.reduce(function(total, cur) {
      return total += cur.length;
    }, 0);
}

content = content.trim()
  .replace(/[\r\n]+/g, '\n')
  .replace(/[ ]+/g, ' ');

var regex_url = /https?:\/\/(:?[\w-]+\.)+[\w-]+\S+\b/g;  // 网址(宽松判断)
var shortUrlCharsNum = 10;
var placeholder = Array(shortUrlCharsNum).fill('囧');

content = content.replace(regex_url, function(matched) {
  // 小于 10 个字符的不使用短网址
  if (fixASC2CharsNum(matched) < shortUrlCharsNum) {
    return matched;
  }

  return placeholder;
});

fixASC2CharsNum(content) > 140;
function dl1 (content) {
  return content
}
function dl2 (content) {
  content = content.trim();
  content = content.replace(/[\n,\s,\r]{2,}/g,' ');
  return content
}
function dl3 (content) {
  content = content.replace(/[\x00-\x7f]{2}/g,"0");
  return content
}
function dl4 (content) {
  content = content.replace(/(https?):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/g,"$10000000000000");
  return content
}
function fn1 (content) {
  content = dl1(content);
  return content.length>140
}
function fn2 (content) {
  content = dl2(content);
  content = dl1(content);
  return content.length>140
}
function fn3 (content) {
  content = dl3(content);
  content = dl2(content);
  content = dl1(content);
  return content.length>140
}
function fn4 (content) {
  content = dl4(content);
  content = dl3(content);
  content = dl2(content);
  content = dl1(content);
  return content.length>140
}

第一题

function getLength(str){
    return str.length > 140
}
let content = '111'
getLength(content); // false

第二题

function getLength(str){
    str = str.replace(/^\s+|\s+$/g,'').replace(/\s+/g,' ');
    return str.length > 140
}
getLength('    123    '); // false
getLength('    12   3    '); // false

第三题

function getLength(str){
    str = str.replace(/^\s+|\s+$/g,'').replace(/\s+/g,' ').replace(/[\x00-\xff]{2}/g, ' ');
    return str.length > 140
}
getLength('    123    '); // false

上述匹配和替换未考虑双字节字符

第四题

function getLength(str) {
    str = str.replace(/^\s+|\s+$/g, '').replace(/\s+/g, ' ').replace(/(http|https):\/\/(\w+(\-\w+)?\.?)(\w+(\-\w+)?)(\.)(\w+(\-\w+)?)(\?\=\&\w+)?/g, 'urlurlurlu').replace(/[\x00-\xff]{2}/g, ' ')
    return str.length > 140
}

测试

// 如果字符数大于 140 返回 true
x = `𠮷 你好啊 ,可还行     流弊
 
  想航海aaaa 5555 78761  1334
` 
console.log('1----', judgeLength_1(x))
console.log('2----', judgeLength_2(x))
console.log('3----', judgeLength_3(x))

第一题

function judgeLength_1(str) {
  return str.length > 140
}

第二题

function judgeLength_2(str) {
  return str.trim().replace(/\s+/g,' ').length > 140
}

第三题

function judgeLength_3(str) {
  let arr = str.trim().replace(/\s+/g,' ').split('')
  let len = arr.reduce((ac, cu)=>{
              return /[\00-\x7f]/.test(cu) ? ac + 0.5 : ac + 1
            }, 0)
  return Math.ceil(len) > 140
} 

第四题

不会

其他

特意去微博上测试了一下, 对于双字节问题,比如 𠮷 ( 不是吉祥的吉),微博上的对话框显示的是两个字节,而且微博也没有做开头(结尾)空格去除,连续空白符的整合,但考虑了ascill 算半个字。

1.png

var pip=(...fn)=>fn.reduce((fn1,fn2)=>(...args)=>fn2(fn1(...args)))
var trim=str=>str.trim().replace(/\s+/g,' ')
var ascii=str=>{
    var ascStr='',len=str.replace(/[\x00-\xff]/g,(s)=>{ascStr+=s; return''}).length
    return {length:len+Math.ceil(ascStr.length/2)}
}
var shortUrl=str=>str.replace(
    /(https*\:\/\/)?([\w\-]+\.)+[\w]{2,6}(\/?\S*)*/g,
    val=>val.length>10?'A'.repeat(10):val
)

// 题1
var gt140=val=>val.length>140
// 题2
var trim_gt140=pip(trim,gt140)
// 题3
var ascii_gt140=pip(trim,ascii,gt140)
// 题4
var shortUrl_gt140=pip(trim,shortUrl,ascii,gt140)
// 第一题
function testLength(str){
    return str.length > 140
}

// 第二题
function testLengthNoSpace(str){
    return testLength(str.trim().replace(/\s+/g,' '))
}

// 第三题
function testLengthNoASCII(str){
    str = str.trim().replace(/\s+/g,' ');
    let ascLen = 0;
    for (let i = 0; i<str.length; i++) {
        str.charCodeAt(i) < 128 && ascLen++
    }
    return str.length - Math.floor(ascLen / 2) > 140
}

// 第四题
function testLengthNoURL(str){
    let placeHolder = Array(21).join(',')
    str = str.trim()
             .replace(/\s+/g,' ')
             .replace(/http:\/\/[\x21-\x7e]{13,}?(?=[^\x21-\x7e]|$)/g, placeHolder)
             .replace(/https:\/\/[\x21-\x7e]{12,}?(?=[^\x21-\x7e]|$)/g, placeHolder)
    return testLengthNoASCII(str)
}
// 第一题
function testLength_one (str) {
   return str.length > 140
}

// 第二题
function testLength_two (str) {
   str = str.replace(/(^\s*)|(\s*$)/g, '').replace(/\s+/g, ' ');
   return str.length > 140
}

// 第三题 不太明白
// 所以第四题也无法回答
const _clearSpaces = (str) => {
  return str = str.trim().replace(/[\s\n\r]+/g, ' ')
}

const _getAscLength = (str) => {
  return [...str].reduce((sum, item) => {
    return sum += /^[\x00-\xff]+$/g.test(item) ? 0.5 : 1
  }, 0)
}
1. 直接比较长度
function validateLength (str) {
  return str.length > 140
}
2. 处理空格后比较长度
function validateSpace (str) {
  return validateLength(_clearSpaces(str))
}
3. 对Ascii处理后比较长度
function validateAsc(str) {
  return Math.ceil(_getAscLength(_clearSpaces(str))) > 140
}
4. 对url处理后比较长度
function validateUrl (str) {
  str = _clearSpaces(str)
  str = str.replace(/https?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9_-](\?)?)*)*/i, ' '.repeat(10))
  return Math.ceil(_getAscLength(str)) > 140
} 
const content = '  大123456家提交1234回答的时候,\n\n注意缩进距离    。https://github.com/zhangxinxu/quiz/issues/18;http://github.com/zhangxinxu  '

function checkLength1(content) {
  return content && content.length > 140 || false
}

function checkLength2(content) {
  if (content) {
    const trimedContent = content.trim()
    // ([\s\n]+)相邻空字符统计为1个字符
    const matchRes = trimedContent.match(/([\s\n]+)|(.)/g)
    return matchRes && matchRes.length > 140 || false
  }
  return false
}

function checkLength3(content) {
  if (content) {
    const trimedContent = content.trim()
    // 统计ASCII字符数量 并除2
    const halfAsciiLength = (trimedContent.match(/([\u00-\uff])/g) || []).length / 2
    const matchRes = trimedContent.match(/([\s\n]+)|(.)/g) || []
    // 只有一半ASCII字符数量计入总数
    return Math.ceil(matchRes.length - halfAsciiLength) > 140
  }
  return false
}

function checkLength4(content) {
  if (content) {
    const placehold = '一'.repeat(10)
    const trimedContent = content.trim()
    // url替换为10长度中文字符串
    const handleUrl = trimedContent.replace(/(https?:\/\/[\w\/\.\?%#&=]*)/g, placehold)
    const halfAsciiLength = (handleUrl.match(/([\u00-\uff])/g) || []).length / 2
    const matchRes = handleUrl.match(/([\s\n]+)|(.)/g) || []
    return Math.ceil(matchRes.length - halfAsciiLength) > 140
  }
  return false
}

console.log(checkLength1(content))
console.log(checkLength2(content))
console.log(checkLength3(content))
console.log(checkLength4(content))
    const content = `其中,题2-题4需求是叠加的,也就是题4的判断需要同时满足题2和题3的需求。

                        大家提交回答的时候,注意缩进距离,起始位置从左边缘开始;另外,github自带代码高亮,所以请使用下面示意的格式。

                        \`\`\`js
                        // 你的JS代码写在这里
                         \`\`\`
                        其它:

                        首位答题者可获得额外2积分和直播翻牌机会;
                        本次答疑直播为4月6日(周六)上午10:00;`;

    function checkLength_1(content){
        return content.length > 140;
    }

    function checkLength_2(content){
        content = content.trim().replace(/[\s]{2,}/g, " ");
        return content.length > 140;
    }

    function checkLength_3(content){
        content = content.trim().replace(/[\s]{2,}/g, " ");
        return Math.ceil(content.length / 2) > 140;
    }

    function checkLength_4(content){
        content = content.trim().replace(/[\s]{2,}/g, " ");
        content = content.replace(/^((https|http|ftp|rtsp|mms){0,1}(:\/\/){0,1})www\.(([A-Za-z0-9-~]+)\.)+([A-Za-z0-9-~\/])+$/g, " ".repeat(10));
        return Math.ceil(content.length / 2) > 140;;
    }

    console.log(checkLength_1(content));
    console.log(checkLength_2(content));
    console.log(checkLength_3(content));
    console.log(checkLength_4(content));
// 第一题
function moreThan140(content = '') {
  return content.length > 140
}
// 第二题
function ignoreSpace140(content = '') {
  return content.replace(/\s/, 'x').replace(/\s/g, 'a').length > 140
}
// 第三题

function asciiContentLength140(content = '') {
  let contetnLength = 0
  contetnLength = content
    .replace(/\s/, 'x')
    .replace(/\s/g, '')
    .replace(/[^\x00-\xff]/g, 'xx').length

  console.log(contetnLength)
  return contetnLength > 140
}
// 第四题

function asciiContentUrlLength140(content = '') {
  let contetnLength = 0
  contetnLength = content
    .replace(/(http|https)\:\/\/\w\S*(\w|\_)\.\S+/g, 'xxxxxxxxxx')
    .replace(/\s/g, '')
    .replace(/[^\x00-\xff]/g, 'xx').length
  console.log(contetnLength)
  return contetnLength > 140
}
String.prototype.isGreater = function(len){
    return this.length > len;
}

String.prototype.filterSPACE = function(){
    return this.trim().replace(/\s+/g, ' ');
}

String.prototype.filterASCII = function(){
    return this.replace(/[\x00-\xff]{2}/gi,"X");
}

String.prototype.filterURI = function(){
    return this.replace(/https?:\/\/[a-z\d\.\-\#\?]+/gi, 'http://t.cn/EiKzyBS​');
}

var content = ` 和建立
         健康
         解决  了较      简介HTTPS://Wd.fffsfffffsfffffsfffffsfffffsfffffsfffffsfffff.hhhjkjkjjjj试试`;
//第一题
content.isGreater(140);

//第二题
content.filterSPACE().isGreater(140);

//第三题
content.filterSPACE().filterASCII().isGreater(140);

//第四题
content.filterURI().filterSPACE().filterASCII().isGreater(140);//有顺序,判断网址最前
第一题
content.length > 140
第二题和第三题
let newContent = content.trim().replace(/\s+/g," ")
newContent.length > 140//第二题
      let unicodeStrs =[]
      let asciiStrs = []
      for (const i of newContent) {
        if(/[\x00-\x7F]/.test(i))asciiStrs.push(i)
        else unicodeStrs.push(i)
      }
let len = unicodeStrs.length+Math.ceil(asciiStrs.length / 2)
len > 140 //第三题
/**
 * @param {string} content 
 * @return {boolean} 字符是否小于指定长度
 */
//第一题
const judgeStrLen = (content, num=140) => {
    if (typeof content !== 'string' || typeof num !== 'number'){
        throw new TypeError('typeof of param is error')
    }

    return content.length > num
}

const handleSpace = s => s.trim().replace(/[\s\\n\\t\\r\\f]+/g, ' ')
const getAsciiLen = s => s.split('').filter(c => c.charCodeAt() < 128).length
const handleURL = s => s.replace(/https?:\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/ig, '0123456789')

//第二题
const judgeStrLen2 = (content, num=140) => {
   //省略参数判断
    return handleSpace(content).length > num
}

//第三题
const judgeStrLen3 = (content, num=140) => {
    content = handleSpace(content)
    let asciiLen = getAsciiLen(content)

    return content.length - asciiLen + Math.ceil(asciiLen/2) > num
}

////第四题
const judgeStrLen4 = (content, num=140) => {
    content = handleSpace(handleURL(content)) //先处理空格对url有误伤
    let asciiLen = getAsciiLen(content)

    return content.length - asciiLen + Math.ceil(asciiLen/2) > num
}
//判断字符串长度
 const getLength =  (text = '', num=140)  => {
     return text.length > num
}
//去除空格,换行以及多个空格为1个字符
const getLengthTrim = (text = '', num = 140) =>{
    return text.trim().replace(/\s+/g,' ').length > num
}
//第三题
const getLengthAsc = (text = '', num = 140) =>{
    const str = text.trim().replace(/\s+/g,' ');
   let len = 0;
    str.split('').forEach((current, index) => len += str.charCodeAt(index).length);
    return Math.ceil(len/2)>num
}
// 长度判断
function judgeLength(str = '', len = 140) {
	return str.length > len
}

// 格式化空格换行
function formatSpace(str = '') {
	return str.trim().replace(/\s+/g, ' ')
}

// 格式化 ASCII
function formatASCII(str = '') {
	return str.replace(/[\x00-\xff]{2}/g, "*")
}

// 格式化 URL
function formatURL(str = '') {
	return str.replace(/https?:\/\/([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)/gm, '网址占位符网址占位符')
}

// 组合函数 从右向左依次调用
function compose(...func) {
    return func.reverse().reduce( function (fn1,fn2) {
        return function(...args) {
            return fn2(fn1(...args));
        };
    } );
}

// 答案和示例

var content = `       
其中,题2-题4需求是叠加的,也就是题4的判断需要同时满足题2和题3的需求。

大家提交回答的时候,https://github.com/zhangxinxu/quiz/issues/18注意缩进距离,起始位置从左边缘开始;另外,github自带代码高亮,所以请使用下面示意的格式。

// 你的JS代码写在这里
其它:

首位答题者可获得额外2积分和直播翻牌机会;
本次答疑直播为4月6日(周六)上午10:00;
http://github.com/maomao1996
		   `

// 第一题
console.log('第一题', judgeLength(content))

// 第二题
function judge2(data) {
	return compose(judgeLength, formatSpace)(data)
}
console.log('第二题', judge2(content))

// 第三题
function judge3(data) {
	return compose(judgeLength, formatASCII, formatSpace)(data)
}
console.log('第三题', judge3(content))

// 第四题
function judge4(data) {
	// 在格式化 ASCII 之前格式化 URL 以免其捣乱
	return compose(judgeLength, formatASCII, formatURL, formatSpace)(data)
}
console.log('第四题', judge4(content))

@maomao1996 代码写的实在太漂亮了,忍不住点个赞

/**
 *
 * 判断一个字符串长度是否大于140
 * @param {string} str
 * @param {*} {
 *              trimAndCombineWhitespace=false, 是否忽略首末尾空白字符以及合并中间的空白字符
 *              combineASCII=false, 是否合并单字节字符
 *              dwz=false, 是否处理短网址
 *            }
 * @returns {boolean} 字符串长度是否大于140
 */
function isGT140(str, { trimAndCombineWhitespace = false, combineASCII = false, dwz = false }={}) {
    //首先判断字符本身是否直接小于140
    if (todoWrap(false)) return false;
    //第一步处理短网址
    if (todoWrap(dwz, todoDwz)) return false;
    //第二步忽略首末尾空白字符以及合并中间的空白字符
    if (todoWrap(trimAndCombineWhitespace, todoTrimAndCombineWhitespace)) return false;
    //第三步合并单字节字符
    if (todoWrap(combineASCII, todoCombineASCII)) return false;
    return true;
    /**
    * 处理的简单包装
    * @param {boolean} needTodo 是否需要进行某个处理
    * @param {function} todoFn 要进行处理的函数
    * @return {boolean|undefined} 是否小于140字符
    */
    function todoWrap(needTodo, todoFn) {
        if (needTodo && todoFn) {
            todoFn()
        }
        if (str.length < 140) {
            return true;
        }
    }
    //处理短网址
    function todoDwz() {
        str = str.replace(/(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?/g, function (match) {
            return match.slice(0, 10);
        });
    }
    //忽略首末尾空白字符以及合并中间的空白字符
    function todoTrimAndCombineWhitespace() {
        str = str.trim().replace(/(\s)\s+/g, '$1');
    }
    //合并单字节字符
    function todoCombineASCII() {
        str = str.replace(/[\x00-\xff]{2}/g, 'a');
    }
}
console.log("第一题");
console.log("  <1>小于140的字符");
console.log(isGT140("a".repeat(130)));
console.log("  <2>大于140的字符");
console.log(isGT140("a".repeat(150)));
console.log("第二题");
console.log("  <1>小于140的字符");
console.log(isGT140(" \t a".repeat(70),{trimAndCombineWhitespace:true}));
console.log("  <1>大于140的字符");
console.log(isGT140(" \t a".repeat(71),{trimAndCombineWhitespace:true}));
console.log("第三题");
console.log("  <1>小于140的字符");
console.log(isGT140(" aa中".repeat(40),{trimAndCombineWhitespace:true,combineASCII:true}));
console.log("  <1>大于140的字符");
console.log(isGT140(" aa中".repeat(50),{trimAndCombineWhitespace:true,combineASCII:true}));
console.log("第四题");
console.log("  <1>小于140的字符");
console.log(isGT140("中a中a中中a中https://github.com/zhangxinxu/quiz/issues/18 \n".repeat(10),{trimAndCombineWhitespace:true,combineASCII:true,dwz:true}));
console.log("  <1>大于140的字符");
console.log(isGT140("中a中a中中a中https://github.com/zhangxinxu/quiz/issues/18 \n".repeat(11),{trimAndCombineWhitespace:true,combineASCII:true,dwz:true}));
// 1、
function isExceeding(content){
    return content.length > 140    
}

// 2~4
function isExceeding2(content){
    var urlReg = /http[s]?:[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/
    return content.trim().replace(/\s+/,' ')   // handle spaces
    .replace(urlReg,'一二三四五六七八九十')      // handle url
    .replace(/[\u0000-\u007F]{2}/,'*')         // handle 128 ascii
        .length > 140
} 
//题目1  判断变量content是否大于140?
var content1=function(values){
  	var ctLength=values.length;
  	if(ctLength>140){
  		alert('字符超出限制!');
  		return false;
  	}
  }
content1('黑耳1');  

//题目2  忽略首尾的空格,然后输入空格、换行等判断变量content是否大于140?
var content2=function(values){
  	//var mobj=values.match(/[\x00-\xff]/gi);
  	var ctLength=values.trim().replace(/\s{1,}\s/gi,'').length;
  	if(ctLength>140){
  		alert('字符超出限制!');
  		return false;
  	}
}
content2(' 234 1 ');

//题目3  相同每两个Ascll字符长度为1个字符(向上取整)等判断变量content是否大于140?
var content3=function(values){
  	var mobj=values.replace(/[\x00-\x7f]{2}/gi,'a');//匹配ASCII值从0-127的字符去除中文 相同两个匹配一个字符
  	var ctLength=mobj.length;
  	if(ctLength>140){
  		alert('字符超出限制!');
  		return false;
  	}
}
content3('22114 1');  

//题目4  所有的(https)地址都可以使用短网址使用,无论多长的地址的字符个数都可以缩短为10个字符,判断此时的变量content是否大于140?
var content4=function(values){
  	var mobj=values.replace(/https?:\/\/[a-z|\d|\.]+/gi,'http://tb.cn');//长网址替换短网址
  	var ctLength=mobj.length; 
  	if(ctLength>140){
  		alert('字符超出限制!');
  		return false;
  	}
}
content4('https://www.baidu.com');  
/**
 * 判断长度
 * @description 判断字符串长度是否大于 140
 * @param {String} content
 * @returns {Boolean}
 */
function isGreater(content) {
  return content.length > 140;
}

/**
 * 过滤空格字符
 * @description 1. 去除内容前后的空格(包括多个的情况) 2. 将内容中的多个 \s 字符替换为单个
 * @param {String} content
 * @returns {String}
 */
function filterSpace(content) {
  var pre = '', preResult = '';
  pre = content.replace(/^(\s+)/mg, '').replace(/(\s+)$/mg, '');
  preResult = pre.replace(/\s+/mg, ' ');
  return preResult;
}


/**
 * 过滤 ascii 码
 * @description 1. 过滤出所有的 ascii 字符,并计算其向上取整的 1/2 长度 2. 将过滤后的内容用占位符补全
 * @param {String} content
 * @returns {String}
 */
function filterAsciiCode(content) {
  var asciiCodeArr = [], calculateAsciiLen = 0, filteredContent = '', returnContent;
  asciiCodeArr = content.split('').filter((item) => item.charCodeAt() >= 0 && item.charCodeAt() <= 127);
  calculateAsciiLen = Math.ceil(asciiCodeArr.length / 2);
  filteredContent = content.replace(/[\x00-\xff]/g, '');
  returnContent = filteredContent.padStart(filterAsciiCode.length + calculateAsciiLen, '占');
  return returnContent;
}

function filterAsciiCode2(content) {
  var filteredContent = '';
  filteredContent = content.replace(/[\x00-\xff]{2}/g, '占');
  return returnContent;
}

/**
 * 过滤网址并补充
 * @description 筛除网址信息并用占位符补充
 * @param {String} content
 * @returns {String}
 */
function filterURL (content) {
  var reg = /(https?):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/mg
  return  content.replace(reg, 'placehold2');
}

/**
 *  工具函数
 * @description 合并函数
 * @param  {... Function} funcs
 */
function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  return funcs.reduce((a, b) => (...args) => a(b(...args)))
}

var myCode = '  ads bk哈哈l k  ';
var composed = compose(isGreater, filterSpace);
composed(myCode);

第一题

compose(isGreater)(content);

第二题

compose(isGreater, filterSpace)(content);

第三题

表述上有歧义。若需要两个 ascii 字符相邻,则为。顺序相关。

compose(isGreater, filterSpace, filterAsciiCode2)(content);

若不需要两个 ascii 字符相邻,则为。顺序相关。

compose(isGreater, filterSpace, filterAsciiCode)(content);

第四题

先对 URL 进行过滤,再进行 ascii 码的验证,最后进行 space 验证。顺序相关。

compose(isGreater, filterSpace, filterAsciiCode, filterURL)(content);
// 第一题
function computeLength1(content) {
    let len = content.length;
    return len;
}

// 第二题
function computeLength2(content) {
    let contentLength = content.length;
    const reg = /\s+/g;
    let res = content.trim().replace(reg, ' ');
    let len = res.length;
    return len;
}

// 第三题
function computeLength3(content) {
    const reg = /\s+/gm;
    let res = content.trim().replace(reg, ' ');
    let asciiNum = 0;
    res.split('').forEach(char => {
        let code = char.charCodeAt(0);
        if (code >= 0 && code <= 127) {
            asciiNum++;
        }
    });
    let minusLen = Math.ceil(asciiNum / 2);
    let len = res.length - minusLen;
    return len;
}

// 第四题
function computeLength4(content) {
    const reg = /\s+/gm;
    const urlReg = /https?:\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/gm
    let res = content.trim().replace(reg, ' ').replace(urlReg, 'xxxxxxxxxx');
    let asciiNum = 0;
    res.split('').forEach(char => {
        let code = char.charCodeAt(0);
        if (code >= 0 && code <= 127) {
            asciiNum++;
        }
    });
    let minusLen = Math.ceil(asciiNum / 2);
    let len = res.length - minusLen;
    return len;
}
// 第一题
content.length > 140

// 第二题
content.trim().replace(/[\r,\n,\s]{2,}/g, " ").length > 140

// 第三题
content.trim().replace(/[\r,\n,\s]{2,}/g, " ").replace(/[\x00-\x7f]{2}/g, " ").length > 140

// 第四题
content.trim().replace(/https?:\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?/g, '*'.repeat(10)).replace(/[\r,\n,\s]{2,}/g, " ").replace(/[\x00-\x7f]{2}/g, " ").length > 140
       function outnumber(num){
            if(num > 140){
                console.log('content字符长度大于140')
            }else {
                console.log('content字符长度不大于140')
            }
        }

        String.prototype.omitspace = function(){
            return this.replace(/\s+/g, ' ').replace(/^\s|\s$/g, '')
        }

        String.prototype.getlength = function(){
            let num = Math.ceil(this.match(/[\x00-\xff]/g).length / 2)
            return this.replace(/[\x00-\xff]+/g, '').length + num
        }

        String.prototype.changeurl = function(){
            return this.replace(/(https?):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/g, '0123456789')     //  照搬前排nichoasurey正则
        }
        outnumber(content.length)
        outnumber(content.omitspace().length)
        outnumber(content.omitspace().getlength())
        outnumber(content.changeurl().omitspace().getlength())
let compare = (function() {
  if (!String.prototype.trim) { //=> 兼容IE9以下
    String.prototype.trim = function() {
      return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
    };
  }

  //=> 第一题
  function normal(content, maxLength) {
    if (content && Object.prototype.toString.call(content) === '[object String]') {
      return content.length > maxLength;
    }
  }

  //=> 第二题
  function blank(content, maxLength) {
    if (content && Object.prototype.toString.call(content) === '[object String]') {
      content = content.trim();
      content = content.replace(/[\s\uFEFF\xA0\n\r]{2,}/g, '一');
      return content.length > maxLength;
    }
  }

  //=> 第三题(这里我理解的是按ASCII个数计算,不管相不相邻)
  function ascii(content, maxLength) {
    if (content && Object.prototype.toString.call(content) === '[object String]') {
      content = content.trim();
      content = content.replace(/[\s\uFEFF\xA0\n\r]{2,}/g, '一');
      let count = 0;
      Array.prototype.forEach.call(content,
      function(item) {
        if (/[\x00-\xff]/.test(item)) {
          count += 1;
        }
      });
      return ((content.length - count) + Math.ceil(count / 2)) > maxLength;
    }
  }

  //=> 第四题
  function link(content, maxLength) {
    if (content && Object.prototype.toString.call(content) === '[object String]') {
      content = content.trim();
      content = content.replace(/https?:\/\/\S+/gi, '一二三四五六七八九十');
      content = content.replace(/[\s\uFEFF\xA0\n\r]{2,}/g, '一');
      let count = 0;
      Array.prototype.forEach.call(content,
      function(item) {
        if (/[\x00-\xff]/.test(item)) {
          count += 1;
        }
      }) return ((content.length - count) + Math.ceil(count / 2)) > maxLength;
    }
  }
  return {
    normal: normal,
    blank: blank,
    ascii: ascii,
    link: link
  }
})();
console.log(compare.normal('1234567890', 140));
console.log(compare.blank(' 1 2 3 \n\rab  cd', 140));
console.log(compare.ascii(' 测 试abcd #  ¥% ', 140));
console.log(compare.link(' \n\r abcd  测试https://www.baidu.com/s?ie=UTF-8&wd=1 测试 32 1', 140));
function isOverLengthOne(str) {
	return str && str.length > 140;
}
function isOverLengthTwo(str) {
	return str && str.trim().replace(/[\n\r ]+/g,' ').length > 140;
}
function isOverLengthThree(str) {
	return str && str.replace(/[\x00-\xff]{2}/g,'1').length > 140;
}
function isOverLengthFour(str) {
	return str && encodeURI(str.trim().replace(/[\n\r ]+/g,' ')).replace(/%20/g,' ').replace(/http[s]?:\/\/([\w%-]+\.)+[\w%-]+(\/[\w-./?%&=]*)?/g,'1234567890').replace(/[\x00-\xff]{2}/g,'1').length > 140;
}
// 第一题
function first(str, len = 140) {
  return str.length > len
}
// 第二题
function second(str) {
  const trimRegex = /(^\s*)|(\s*$)/g
  const spaceRegex = /(\s+)|(\n+)|(\r\n+)/g
  return str.replace(trimRegex, '').replace(spaceRegex, ' ')
}
// 第三题
function third(str) {
  return second(str).replace(/[\x00-\xff]{2}/g, 'a')
}
// 第四题 
function fourth(str) {
  const regex = /(https?):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/g
  return third(second(str).replace(regex, '十个非美国信息交换码'))
}
const a = `            abc        

aaa.
       
a. 
https://developer.mozila.org

a`
const one = first(a)
const two = first(second(a))
const three = first(third(a))
const four = first(fourth(a))
function charJudge1(content) {
    return content.length > 140;
  }

  function charJudge2(content) {
    //方法1
    //   var str = content.replace(/(^\s*)|(\s*$)/g,"").replace(/\s+/g, ' ').replace(/[\r\n]/g, ' ');
    //方法2 IE9以上和其他浏览器支持trim
    var str = content.trim().replace(/\s+/g, ' ')
      .replace(/[\r\n]/g, ' ')
      .replace(/[\x00-\xff]{2}/gi, ' ')
      .replace(/(http|https|HTTP|HTTPS):\/\/([\w.]+\/?)\S*/, 'xxxxxxxxxx');
    return str.length > 140;
  }
  //  第一题
  function first(content){
     return content.length>140
  }
  function mytrim(str){
    return str.trim().replace(/\s+/g,' ')
  }
  // 第二题
  function second(content){
    return mytrim(content).length>140
  }
  // 第三题
  function three(content){
    return Math.ceil((mytrim(content).length)/2)>140
  }
  // 第四题
  function four(content){
    let str = content.replace(/https:\/\/|http:\/\//,"")
    return three(str)
  }
// 1.
function stringOverLength(content) {
    return content.length > 140
}

//2.
function stringOverLengthIgnoreSpace(content) {
    return content.trim().replace(/\s+/g, ' ').length > 140
}

//3.
function stringOverLengthIgnoreSpaceASCII(content) {
    return Math.ceil(Array.prototype.reduce.call(
        content.trim().replace(/\s+/g, ' '),
        function (total, cur) {
            console.log(cur, cur.charCodeAt)
            if (/[^\x00-\xff]+$/g.test(cur)) {
                return total + 1
            }
            return total + 0.5
        }, 0)
    ) > 140
}

//4.
function stringOverLengthIgnoreSpaceASCIIHttp(content) {
    return stringOverLengthIgnoreSpaceASCII(
        content.replace(/https?:\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/gm, '----------')
    )
}
  1. 空格替换直接trim()方法,以及/\s+/g正则即可;
  2. ASCII字符非连续也算半个字符,可以使用str.match(/[\x00-\xff]/g).length;
  3. 网址优先判断;
  4. 替换的字符务必是非ASCII字符(否则会认为是5个字符长度);
  5. 20个ASCII字符长度,可以Array(20).join()或者','.repeat(20);