导航


HTML

CSS

JavaScript

浏览器 & 网络

版本管理

框架

构建工具

TypeScript

性能优化

软实力

算法

UI、组件库

Node

冷门技能

⭐ 写一个提取 URL 参数的 js 方法

例如:url="[<https://alibaba.com?a=1&b=2&c=3#hash>"](<https://alibaba.com/?a=1&b=2&c=3#hash%22>)

要求:识别 queryParam

let url = "<https://alibaba.com?a=1&b=2&c=3#hash>"
function getParamFromURL(url) {
 //...your code
}
const url = "<https://alibaba.com?a=1&b=2&c=3#hash>";
function getParamFromURL(url){ //定义函数
  var pattern = /(\\w+)=(\\w+)/ig;//定义正则表达式
  var params = {};//定义数组
  url.replace(pattern, function(a, b, c) {
    console.log(a, b, c); // a=1 a 1; b=2 b 2; c=3 c 3
    params[b] = c;
  });
  return params;//返回这个对象.
}
console.log(getParamFromURL(url));

或者

const url = "<https://alibaba.com?a=1&b=2&c=3#hash>";
function getParamFromURL(url){ //定义函数
  const reg = /(\\w+)=(\\w)/ig;
  const arr = url.match(reg) ?? []; // 防止为 null | [ 'a=1', 'b=2', 'c=3' ]
  const obj = {};
  for (const item of arr) {
    const [key, value] = item.split('=');
    obj[key] = value;
  }
  return obj;
}
console.log(getParamFromURL(url));

或者原生 API

const url = "<https://alibaba.com?a=1&b=2&c=3#hash>";
function queryURLParams(URL) {
  let url = URL.split("?")[1];
  const urlSearchParams = new URLSearchParams(url);
  const params = Object.fromEntries(urlSearchParams.entries());
  return params
}
console.log(queryURLParams(url))

如何将浮点数点左边的数每三位添加一个逗号,如 12000000.11 转化为『12,000,000.11』?

// 从后往前,每三个为一次循环,最前面加,
// ,000
// ,000,000
// 12,000,000
function toThousands(num) {
    if (typeof num !== 'number') return 0;
    var flag = "";
    if (num < 0) {
        flag = "-";
        num = Math.abs(num);
    }
    // 转为数组 [ '12000000', '11' ]
    var arr = num.toString().split(".");
    // 截取.左边和右边存起来
    var left = [...arr[0]];
    var right = "";
    if (arr.length > 1) {
        right = "." + arr[1];
    }
    var count = left.length - 1;
    // 操作左边整数部分,逆向遍历并且逢3前面加个"," i-1
    while (count > 0) {
        // [1,2,0,0,0,0]
        // 例如如果数组长度为6,则一开始count=5,不加,
        // count=3时,就需要在前面加个,
        if (count % 3 === 0) {
            left.splice(-count, 0, ',');
        }
        count--;
    }
    // 正负符号+左边+小数点和右边
    return flag + left.join("") + right;
}
// 正则
function toThousands(num) {
  return num && num
    .toString()
    .replace(/(\\d)(?=(\\d{3})+\\.)/g, function($1, $2){
    return $2 + ',';
  });
}
// toLocaleString

// 利用 toLocaleString() 返回某语言系统下数字的表示字符串 IE6+
var num = 12000000.11
num.toLocaleString()

字符串去重

var str = "111222333000aaa我我我";

String.prototype.myUnique = function() {
	var hash = {},
      newStr = "";
  
  for (var i = 0; i < this.length; i++) {
  	if (!hash.hasOwnProperty(this[i])) {
    	hash[this[i]] = this[i];
      newStr += this[i];
    }
  }
  
  return newStr;
};

console.log(str.myUnique());
// 或者
 String.prototype.myUnique = function() {
	 return Array.from(new Set(this.split('')));
 }

找出一串字符串中所有只出现一次的字符的索引组成的数组

var str = "saso1idangvcas3gkxkxlaknzgegunclas";

function test(str) {
	var hash = {},
      newArr = [];
  
  for (var i = 0; i < str.length; i++) {
    var item = str[i];
  	if (!hash.hasOwnProperty(item)) {
    	hash[item] = 1;
    } else {
    	hash[item]++;
    }
  }
  
  console.log(hash);
  
  for (var i = 0; i < str.length; i++) {
  	if (hash[str[i]] === 1) {
      console.log(str[i]);
    	newArr.push(i);
    }
  }
  
  return newArr;
}

console.log(test(str));

或者

var str = "saso1idangvcas3gkxkxlaknzgegunclas";

function test(str) {
  let arr = [];

  str.split("").forEach((char) => {
    const firstIdx = str.indexOf(char);
    const lastIdx = str.lastIndexOf(char);
    if (firstIdx === lastIdx) {
      arr.push(firstIdx);
    }
  });

  return arr;
}

console.log(test(str));

判断一个给定的字符串是否是同构的

输入: s = "egg", t = "add"
输出: true
输入: s = "foo", t = "bar"
输出: false

function isIsomorphic(a, b) {
  let i = 0;
  while(i < a.length) {
    if (a.indexOf(a[i]) !== b.indexOf(b[i])) {
      return false;
    }
    i++;
  }
  return true;
}
console.log(isIsomorphic('egg', 'add'));

实现模糊搜索结果的关键词高亮显示

const keyword = '项目开发';
const str = 'Vue.js项目开发实战';
console.log(
  str.replace(
    new RegExp(keyword, 'i'),
    `<b style="color: #2D7BFF">${keyword}</b>`
  )
);

来源:https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/141#

判断一个单词是否是回文

var str = "mamam";
function checkPalindrom(str) {
    return str == str.split('').reverse().join('');
}

⭐ 验证回文字符串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

var str = "A man, a plan, a canal: Panama"
var isPalindrome = function (s) {
    var reg = /[^A-Za-z0-9]/g
    var tempStr = s.replace(reg, "")
    var reverseStr = tempStr.split("").reverse().join("")
    return reverseStr.toLowerCase() === tempStr.toLowerCase()
};

console.log(isPalindrome(str))

统计字符串出现最多的字母

var str = "afjghdfraaaasdenas";

function findMaxDuplicateChar(str) {
    if (str.length == 1) return str;
    let charObj = {};
    for (let i = 0; i < str.length; i++) {
        if (!charObj[str.charAt(i)]) {
            charObj[str.charAt(i)] = 1;
        } else {
            charObj[str.charAt(i)] += 1;
        }
    }
    let maxChar = '',
        maxValue = 1;
    for (var key in charObj) {
        if (charObj[key] >= maxValue) {
            maxChar = key;
            maxValue = charObj[key];
        }
    }
    return maxChar;
}

字符串中的第一个唯一字符

给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。

var str = "leetcode"
function firstUniqChar(str) {
  for (var i = 0; i < str.length; i++) {
    var curChar = str[i]
    if (str.lastIndexOf(curChar) === str.indexOf(curChar)) {
      return i
    }
  }
  return -1
}
console.log(firstUniqChar(str))

有效的字母异位词

即判断字符串中是否只有字符的位置不同,也就是判断两个字符串中包含的字符以及这些字符出现的次数是否相同

var s = "anagram", t = "nagaram"
function isAnagram(s, t) {
  if (s.length !== t.length) return false;
  var ss = s.split("").sort().join("")
  var tt = t.split("").sort().join("")
  return ss === tt ? true : false
}
console.log(isAnagram(s, t));

实现 String.prototype.indexOf

// 简化版
var ss = "aabbaaa", s = "bba"
var strStr = function (ss, s) {
    if (ss.length < s.length) return -1
    for (let i = 0; i < ss.length; i++) {
       if (ss.slice(i, i + s.length) === s) {
          return i
       }
    }
    return -1
};
console.log(strStr(ss, s))

// 详细版
var prop = String.prototype
prop.myIndexOf = function myIndexOf(searchElement, fromIndex) {
    if (!fromIndex || fromIndex < 0) {
        fromIndex = 0
    }
    var len = this.length
    if (fromIndex >= len) return -1
    for (var i = 0; i < len; i++) {
        var resultIndex = i + fromIndex
        if (this.slice(resultIndex, resultIndex + searchElement.length) === searchElement) {
            return resultIndex
        }
    }
    return -1
}
console.log(ss.myIndexOf(s))
console.log(ss.indexOf(s))

// 正则
var prop = String.prototype
prop.myIndexOf = function myIndexOf(searchElement, fromIndex) {
    var reg = new RegExp(searchElement)
    // 判断 fromIndex 的合法性(没传或传的小于0,则相当于从头查起)
    if (!fromIndex || fromIndex < 0) {
        fromIndex = 0
    }
    // 超出返回-1
    if (fromIndex >= this.length) return -1
    var target = this.slice(fromIndex)
    return reg.exec(target) ? reg.exec(target).index + fromIndex : -1
}

console.log(ss.myIndexOf(s))
console.log(ss.indexOf(s))

⭐ 报数

报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:

1.     1
2.     11
3.     21
4.     1211
5.     111221

1 被读作  "one 1"  ("一个一") , 即 11

11 被读作 "two 1s" ("两个一"), 即 21

21 被读作 "one 2",  "one 1" ("一个二" ,  "一个一") , 即 1211

function countAndSay(n) {
    let result = "1";
    let repeatCount = 1;
    for (let i = 1; i < n; i++) { // 报数总轮数, n = 1 时不需要报数, 直接返回
        let current = "";
        for (let j = 0; j < result.length; j++) { // 当轮要报数的目标
            if (result[j] === result[j + 1]) { // 从前往后两两比较,一致则累加重复次数,否则立马读数
                repeatCount++;
            } else {
                current += repeatCount + result[j]; // 读数
                repeatCount = 1; // 重置累加次数
            }
        }
        result = current; // 每趟读完, 更新报数目标
    }
    return result;
}

// 测试用例
console.log(countAndSay(4));  // 输出: "1211"
console.log(countAndSay(1));  // 输出: "1"

⭐ 最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""

var arr = ["flower", "flow", "flight"]
function longestCommonPrefix(arr) {
    if (!arr.length) return ""
    var firstStr = arr[0]
    var result = ""
    
    for (var i = 0; i < firstStr.length; i++) {
        for (var j = 1; j < arr.length; j++) {
            if (firstStr[i] !== arr[j][i]) {
                return result
            }
        }
        result += firstStr[i]
    }
    return result
}
console.log(longestCommonPrefix(arr))

如何把一个字符串的大小写取反(大写变小写小写变大写),例如 ’AbC' 变成 'aBc'

// 方法一:常规
function transformStr(str) {
    let tempArr = str.split('')
    let result = tempArr.map(char => {
        return char === char.toUpperCase() ? char.toLowerCase() : char.toUpperCase()
    })
    return result.join('')
}
console.log(transformStr('aBc'))
// 方法二:正则
'aBc'.replace(/[A-Za-z]/g, char => char === char.toUpperCase() ? char.toLowerCase() : char.toUpperCase())

题目来源:Daily-Interview-Question 第69题

随机生成指定长度的字符串

// 目标:比如给定 长度 8  输出 4ldkfg9j
function randomString(n) {  
  let str = 'abcdefghijklmnopqrstuvwxyz9876543210';
  let tmp = '',
      i = 0,
      l = str.length;
  for (i = 0; i < n; i++) {
    tmp += str.charAt(Math.floor(Math.random() * l));
  }
  return tmp;
}

实现模糊搜索结果的关键词高亮显示

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>autocomplete</title>
    <style>
      bdi {
        color: rgb(0, 136, 255);
      }
      li {
        list-style: none;
      }
    </style>
  </head>
  <body>
    <input class="inp" type="text" />
    <section>
      <ul class="container"></ul>
    </section>
  </body>
  <script>
    function debounce(fn, timeout = 300) {
      let t;
      return (...args) => {
        if (t) {
          clearTimeout(t);
        }
        t = setTimeout(() => {
          fn.apply(fn, args);
        }, timeout);
      };
    }
    function memorize(fn) {
      const cache = new Map();
      return (name) => {
        if (!name) {
          container.innerHTML = "";
          return;
        }
        if (cache.get(name)) {
          container.innerHTML = cache.get(name);
          return;
        }
        const res = fn.call(fn, name).join("");
        cache.set(name, res);
        container.innerHTML = res;
      };
    }
    function handleInput(value) {
      const reg = new RegExp(`\\(${value}\\)`);
      const search = data.reduce((res, cur) => {
        if (reg.test(cur)) {
          const match = RegExp.$1;
          res.push(`<li>${cur.replace(match, "<bdi>$&</bdi>")}</li>`);
        }
        return res;
      }, []);
      return search;
    }
    const data = [
      "上海野生动物园",
      "上饶野生动物园",
      "北京巷子",
      "上海中心",
      "上海黄埔江",
      "迪士尼上海",
      "陆家嘴上海中心",
    ];
    const container = document.querySelector(".container");
    const memorizeInput = memorize(handleInput);
    document.querySelector(".inp").addEventListener(
      "input",
      debounce((e) => {
        memorizeInput(e.target.value);
      })
    );
  </script>
</html>