interview
frontend-classic
如何使用JS判断某个字符串长度(要求支持Emoji表情)?

前端经典面试题合集, 如何使用 JS 判断某个字符串长度要求支持 Emoji 表情?

前端经典面试题合集, 如何使用 JS 判断某个字符串长度要求支持 Emoji 表情?

QA

Step 1

Q:: 如何使用 JS 判断某个字符串长度(要求支持 Emoji 表情)?

A:: 在 JavaScript 中,传统的字符串长度计算方法 (string.length) 无法正确处理包含 Emoji 表情的字符串。因为某些 Emoji 表情由两个或更多的 UTF-16 单元组成,string.length 会把每个单元都算成一个字符。我们可以使用 JavaScript 的扩展字符匹配方式来正确计算字符串长度,例如 Array.from(string).length 或 [...string].length,它们都能正确处理 Emoji 表情。 示例代码:

 
function getStringLength(str) {
  return Array.from(str).length;
}
console.log(getStringLength('Hello World! 😊')); // 输出: 14
 

Step 2

Q:: 如何区分 JS 中的 undefined 和 null?

A:: 在 JavaScript 中,undefined 和 null 都表示空值,但有细微的区别。undefined 表示一个变量已经声明但尚未赋值,而 null 是一个表示'没有值'的对象。使用 typeof 运算符可以区分它们:typeof undefined 返回 'undefined',typeof null 返回 'object'。此外,可以使用严格相等运算符 (===) 进行比较。 示例代码:

 
let a;
let b = null;
console.log(a); // 输出: undefined
console.log(b); // 输出: null
console.log(a === undefined); // 输出: true
console.log(b === null); // 输出: true
console.log(a === b); // 输出: false
 

Step 3

Q:: 解释 JS 中的事件冒泡与事件捕获机制

A:: 事件冒泡与事件捕获是 JavaScript 事件传播的两种机制。在事件冒泡阶段,事件从最具体的元素开始,逐级向上传播到最不具体的元素(通常是 document)。而在事件捕获阶段,事件从最不具体的元素开始,逐级向下传播到最具体的元素。 示例代码:

 
<!DOCTYPE html>
<html>
<head>
  <title>事件冒泡与捕获</title>
</head>
<body>
  <div id="outer">
    <button id="inner">点击我</button>
  </div>
  <script>
    document.getElementById('outer').addEventListener('click', function() {
      console.log('Outer DIV 捕获');
    }, true);
    document.getElementById('inner').addEventListener('click', function() {
      console.log('Inner BUTTON 捕获');
    }, true);
    document.getElementById('outer').addEventListener('click', function() {
      console.log('Outer DIV 冒泡');
    }, false);
    document.getElementById('inner').addEventListener('click', function() {
      console.log('Inner BUTTON 冒泡');
    }, false);
  </script>
</body>
</html>
 

这个例子展示了事件在捕获和冒泡阶段的行为。

用途

这些内容是前端开发中的基础知识,了解它们有助于开发者编写更加健壮和高效的代码。在实际生产环境中,字符串处理、事件处理和基本数据类型是日常开发中经常会用到的。正确计算字符串长度可以避免在处理用户输入时出现错误,区分 undefined 和 null 有助于避免逻辑错误,而理解事件传播机制可以帮助开发者更好地管理用户交互事件。\n

相关问题

🦆
如何在 JavaScript 中深拷贝一个对象?

深拷贝一个对象可以使用 JSON.parse 和 JSON.stringify 方法,但这不适用于对象包含函数或 undefined 的情况。另一种方法是使用递归拷贝或结构化克隆算法。 示例代码:

 
function deepCopy(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }
  let copy = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      copy[key] = deepCopy(obj[key]);
    }
  }
  return copy;
}
 
🦆
解释 JavaScript 的闭包closure概念及其用途

闭包是指函数可以记住并访问其词法作用域,即使这个函数在其词法作用域之外执行。闭包使得函数拥有'私有'变量,可以避免全局污染。 示例代码:

 
function createCounter() {
  let count = 0;
  return function() {
    return ++count;
  };
}
const counter = createCounter();
console.log(counter()); // 输出: 1
console.log(counter()); // 输出: 2
 
🦆
JavaScript 中的防抖动和节流是什么,有什么区别?

防抖动(debounce)和节流(throttle)都是优化高频率事件(如滚动、窗口大小改变等)触发频率的方法。防抖动是在事件停止触发 n 秒后才执行函数,如果在这段时间内再次触发,则重新计时。而节流是在一定时间内只执行一次函数。 防抖动示例代码:

 
function debounce(func, wait) {
  let timeout;
  return function(...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(this, args), wait);
  };
}
 

节流示例代码:

 
function throttle(func, limit) {
  let lastFunc;
  let lastRan;
  return function(...args) {
    if (!lastRan) {
      func.apply(this, args);
      lastRan = Date.now();
    } else {
      clearTimeout(lastFunc);
      lastFunc = setTimeout(() => {
        if (Date.now() - lastRan >= limit) {
          func.apply(this, args);
          lastRan = Date.now();
        }
      }, limit - (Date.now() - lastRan));
    }
  };
}