前端手写题之正则表达式
正则表达式
前端手写题集锦 use js 记录大厂面试常考手写题,github仓库地址:https://github.com/Sunny-117/Front-end-handwritten-question。伴随秋招陆续更新,求star
正则表达式模版字符串
String.prototype.render = function (data) { return this.replace(/{{[.\s\S]*?}}/g, match => { if ((match = match.substring(2, match.length - 2).trim()) == "") { return ""; } else if (match.startsWith("#")) { return eval(match.substr(1, match.length - 1)); } else { return data[match] ? data[match] : ""; } }) } const data = { name: "小明", age: 16, school: "第三中学", classroom: "教室2" } console.log( "{{ name }} 今年 {{ age }} 岁,就读于 {{ school }} 今天在 {{ classroom }} 上课,{{ name }} {{ #data.age >= 18 ? '成年了' : '未成年' }}".render(data) ); // 小明 今年 16 岁,就读于 第三中学 今天在 教室2 上课,小明 未成年 console.log( `{{name}}说了句{{# if (data.age >= 18) { "我已经成年了!" } else { "我还没有成年!" } }}`.render(data) ); // 小明说了句我还没有成年!
常写
// 手机号 let reg1 = /^1[44578]\d{9}$/g; let str1 = '159****9999' console.log(reg1.test(str1)); // qq号 let reg2 = /^[1-9][0-9]{4,9}$/g; let str2 = '159222' console.log(reg2.test(str2)); // 颜色 let reg3 = /#?([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/g; let str3 = '#abc' console.log(reg3.test(str3)); // 邮箱 let reg4 = /^([A-za-z0-9_\-\.]+)+@([A-za-z0-9_\-\.]+)\.([A-Za-z]{2, 6})$/g;//+一到多 var reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/; let str4 = 'a11bc@didi.com' console.log(reg4.test(str4));
字符串的大小写取反
let str = "QIANDUANGOngchengshi猕猴桃Jquery很帅!哈哈 haha"; str = str.replace(/[a-zA-Z]/g, (content) => { return content.toUpperCase() === content ? content.toLowerCase() : content.toUpperCase(); }); console.log(str);
检验字符串首尾是否含有数字
let reg = /^\d|\d$/g;//或 let reg2 = /^\d[\s\S]*\d$/g;//都
去除字符串空格
var str = ' as ' //方法1 str = str.replace(/\s*/g,"");//去除所有空格 str = str.replace(/^\s*|\s*$/g,"");//去除两头空格 str = str.replace(/^\s*/,"");//去除左边空 str = str.replace(/(\s*$)/g,"");//去除右边空格 //方法2:trim()方法:只能去除两边空格 function trim(str) { if (str && typeof str === "string") { return str.replace(/(^\s*)|(\s*)$/g, "");//去除前后空白符 } } //方法3 jquery $.trim(str) var str = "a2119naskdna"; var newStr = str.replace(/[a-zA-Z]/g, '');//别忘了方括号 console.log(newStr); const str = ` <div>第一个div</div> <p>第一个p</p>` function extract(str) { return str.replace(/<[^<>]+>/g, ""); } console.log(extract(str));
驼峰
//横线式 let str = 'hello-world' function getCamelCase(str) { let reg = /-(\w)/g; return str.replace(reg, (_, match) => match.toUpperCase()) } console.log(getCamelCase(str))// helloWorld let a='hello world' let b = a.replace((/\s\w/g),function(v){ return v.substring(1).toUpperCase() }) console.log(b) const str = 'helloWorld'; function getKebabCase(str) { let arr = str.split(''); let result = arr.map((item) => { if (item.toUpperCase() === item) { return '-' + item.toLowerCase(); } else { return item; } }).join(''); return result; } console.log(getKebabCase(str)); function hump2Underline(s) { return s.replace(/([A-Z])/g, '_$1').toLowerCase() }
对象key的驼峰转下划线
const humpToUnderline = function (name) { let newName = ""; for (const c of name) { if (c.charCodeAt() <= "Z".charCodeAt() && c.charCodeAt() >= "A".charCodeAt()) { newName += "_" + c.toLowerCase(); } else { newName += c; } } return newName; }; const formatPropertyNamesB = function (obj) { const names = []; const unenumerable = {}; for (const key in obj) { // 属性可配置才进行操作,不可配置的属性忽略 if (Object.getOwnPropertyDescriptor(obj, key).configurable) { names.push(key); } } // 获取自身的不可枚举但可配置的属性 for (const key of Object.getOwnPropertyNames(obj)) { if (names.indexOf(key) === -1 && Object.getOwnPropertyDescriptor(obj, key).configurable) { unenumerable[key] = Object.getOwnPropertyDescriptor(obj, key); } } // 处理可迭代属性 for (const key of names) { const newKey = humpToUnderline(key); obj[newKey] = obj[key]; delete obj[key]; } // 处理不可迭代属性 for (const key in unenumerable) { const newKey = humpToUnderline(key); Object.defineProperty(obj, newKey, unenumerable[key]); delete obj[key]; } }; // 有带有属性配置的对象 const person2 = { userName: "Dasen", userCurrentAge: 23, }; Object.defineProperty(person2, "nickName", { configurable: false, enumerable: true, value: "Dear Dasen", }); // nickName 属性不可配置,删除操作会静默失败,结果会多一个重复的属性 nick_name // formatPropertyNamesA(person2); // {nickName: 'Dear Dasen', user_name: 'Dasen', user_current_age: 23, nick_name: 'Dear Dasen'} formatPropertyNamesB(person2); console.log(person2); // {nickName: 'Dear Dasen', user_name: 'Dasen', user_current_age: 23} console.log(Object.getOwnPropertyDescriptor(person2, "nickName")); // {value: 'Dear Dasen', writable: false, enumerable: true, configurable: false}
json对象的key驼峰式转下划线,可以指定层级 递归
function underline2Hump(s) { return s.replace(/_(\w)/g, function (all, letter) { return letter.toUpperCase() }) } // JSON对象的key值转换为驼峰式 function jsonToHump(obj) { if (obj instanceof Array) { obj.forEach(function (v, i) { jsonToHump(v) }) } else if (obj instanceof Object) { Object.keys(obj).forEach(function (key) { var newKey = underline2Hump(key) if (newKey !== key) { obj[newKey] = obj[key] delete obj[key] } jsonToHump(obj[newKey]) }) } } const obj = { demo_demo: 'demo', a_d: 1, abcDem: [{ arr_arr: 123 }] } jsonToHump(obj) console.log(obj);
连续的0去掉
var str = "013d1we22ewfa33rr4rwq0dsf00dsf9fas999"; var getNum = function (Str, isFilter) { //用来判断是否把连续的0去掉 isFilter = isFilter || false; const finallyResult = []; // 精髓在正则 var arr = Str.match(isFilter ? /[1-9]\d{1,}/g : /\d{2,}/g); const result = arr.map(ele => ele); console.log(result); //连续数字的数组 for (let i = 0; i < result.length; i++) { if (result[i].length === 3) { finallyResult.push(result[i]); } } return finallyResult; // 连续的三个数字 }; console.log(getNum(str));
正则
let str = '((2+3)+(3*4))+2' function print(str) { const res = [] matchRes = '' str = str.replace(/\(\(([\d\D]+)\)\)/g, function (match) { matchRes = match.substring(1, match.length - 1) res.push(matchRes) }) matchRes.replace(/\([\s\S]+?\)/g, function (match) { // 非贪婪匹配 res.push(match) }) return res } console.log(print(str));// ['(2 + 3)+(3 * 4)', '2 + 3', '3 * 4']