刷题 | 牛客 - js简单10题(更ing)1/10知识点解答
知识点总结:
str.charCodeAt(位置)——返回指定位置的Unicode编码,不支持 超过 0xFFFF
的字符(emoji、生僻字)(即不支持 码点 > 65535,仅支持常规字符 如英文、数字), JS中 String
(字符串)对象的方法
str.codePointAt(位置)——返回指定位置的完整码点(含),es6新增,支持所有编码(可以超出65535),支持代理对(即 支持高位字符,如 索引0),
.fromCodePoint()
—— 可反向转换字符,用于从一个或多个 Unicode 码点创建字符串,支持完整的 Unicode 字符,包括 emoji、生僻字等超出 0xFFFF 的码点。
for循环:
场景 | 建议使用 |
---|---|
遍历普通对象属性 | for...in ✅ |
遍历数组或字符串 | for...of ✅ |
需要同时获取索引和值 | arr.entries() 搭配 for...of |
遍历 Map、Set | for...of ✅ |
使用对象中自定义方法或原型方法 | for...in 会包括它们,要注意过滤 |
链式调用、柯里化、闭包:
闭包(Closure):函数访问外部函数作用域的变量。【用于:① 数据私有化(模拟私有变量);②实现记忆缓存;③异步场景保存上下文】【写法:function outer() { return function inner() {} }
】
柯里化(Currying):把一个多参数函数,转为每次只传一个参数的函数链式调用形式。【用途:1. 预设参数;2.实现函数复用(高阶函数)】【写法:fn(a)(b)(c)
】
链式调用(Chaining):连续调用多个方法或函数。常见于 jQuery
、Vue
、Promise
、axios
等库;核心:函数 返回自身 或返回另一个函数对象。【典型写法:obj.fn1().fn2()
】
JS48 获取字符串的长度
描述
如果第二个参数 bUnicode255For1 === true,则所有字符长度为 1
否则如果字符 Unicode 编码 > 255 则长度为 2
示例1
输入:
'hello world, 牛客', false
输出:17
解答
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><style>/* 填写样式 */</style>
</head><body><!-- 填写标签 --><script type="text/javascript">// 填写JavaScriptfunction strLength(s, bUnicode255For1) {// 思想:求字符串中的unicode编码,并求对应的长度// 法一(两种写法):str.charCodeAt(i) 方法,求对应位置i上的字符的 Unicode编码/*let res = 0;if(bUnicode255For1){return s.length;}else{const arr = s.split('');for(let i=0;i<arr.length;i++){let len = arr[i].charCodeAt(0) > 255 ? 2 : 1;res += len; }return res;}*//*let length = s.length;if(!bUnicode255For1){for(let i in s){if(s.charCodeAt(i) > 255){length++;}}}return length;*/// 法二: codePointAt ,支持所有Unicode/*let res = 0;if(bUnicode255For1){return s.length;}else{const arr = s.split('');for(let i=0;i<arr.length;i++){let len = arr[i].codePointAt(0) > 255 ? 2 : 1; res += len;}return res;}*/let length = s.length;if(!bUnicode255For1){for(let i in s){if(s.codePointAt(i) > 255){length++;}}}return length;}</script>
</body></html>
知识点
字符串方法
✅ 1. str.charCodeAt(位置) —— 求
位置中的字符 的 Unicode 编码
是 JavaScript 中 String
(字符串)对象的方法
返回的是指定位置的字符的 Unicode 编码(UTF-16 编码单元)。
-
参数:
index
,必需,整数,表示字符在字符串中的位置(从0
开始计数)。 -
返回:该位置字符的 Unicode 编码(0~65535 之间的十进制数字)。
-
如果
index
超出范围,返回NaN
。 -
适合 BMP 基本多文种字符,即 普通英文、数字、拉丁字母
const code = 'A'.charCodeAt(0);
console.log(code); // 输出:65(即 'A' 的 Unicode 编码)
返回的是字符的 UTF-16 编码单元(16位以内)
适合处理普通英文、数字、拉丁字母等基本字符
例子:
let str = "ABC";console.log(str.charCodeAt(0)); // 65 -> 'A' console.log(str.charCodeAt(1)); // 66 -> 'B' console.log(str.charCodeAt(2)); // 67 -> 'C' console.log(str.charCodeAt(3)); // NaN -> 越界
注:
charCodeAt
不能识别完整 emoji 或 Unicode 扩展字符(码点 > 65535)如何获取完整的Unicode编码(码点):
使用 codePointAt( )——》即 使用
codePointAt()
处理 emoji 和高位字符 更准确console.log("😀".codePointAt(0)); // 128512(十进制)即 U+1F600
✅ 2. str.codePointAt(位置) ——【ES6 引入】
——(支持所有 Unicode 字符,推荐 👍)
codePointAt()
是 JavaScript ES6 引入的 字符串方法,用于返回指定位置处字符的 Unicode 码点(code point),即完整的 Unicode 编码(支持 emoji 和高位字符)。
语法:str.codePointAt(position)
- position:字符串中某个字符的位置(索引,从 0 开始)
- 返回字符的 Unicode 码点(十进制数)
- 如果超出字符串范围,返回 undefined
实际应用场景
1. 判断字符串是否包含高位字符(如 emoji)
function hasHighCodePoint(str) {for (let ch of str) {if (ch.codePointAt(0) > 0xffff) {return true;}}return false; } console.log(hasHighCodePoint("hi😀")); // true
2. 获取字符的 Unicode 编码(十六进制)
let ch = '𠮷'; // 中文“吉”字的异体字 console.log(ch.codePointAt(0).toString(16)); // 20bb7
注意事项
✅
codePointAt()
支持代理对(surrogate pair)
JS 字符串是基于 UTF-16,每个字符最多用两个编码单元(2×16位)
对于编码大于
0xFFFF
的字符(如 emoji),使用codePointAt()
可以正确获取 完整码点✅ 使用
fromCodePoint()
可反向转换字符
let cp = "😄".codePointAt(0);
console.log(String.fromCodePoint(cp)); // 😄
fromCodePoint()
和String.fromCharCode()
区别
方法 是否支持代理对(高位字符) 返回值范围 String.fromCharCode()
❌ 不支持,仅支持 BMP 区域 0 ~ 65535 (0xFFFF) String.fromCodePoint()
✅ 支持所有 Unicode 字符 0 ~ 0x10FFFF
例子:
const code = '𠮷'.codePointAt(0);console.log(code); // 输出:134071(大于 0xFFFF 的字符)
支持高位字符(例如 emoji、汉字扩展等)
返回完整的 Unicode 码点值(即十进制)
let emoji = "😄"; // Unicode 编码是 U+1F604console.log(emoji.codePointAt(0)); // 128516 ✅ console.log(emoji.charCodeAt(0)); // 55357 ❌(高位代理项) console.log(emoji.charCodeAt(1)); // 56836 ❌(低位代理项)
str.codePointAt( ) 总结
项目 | 内容 |
---|---|
方法 | str.codePointAt(index) |
返回 | Unicode 码点(十进制) |
用途 | 获取任意字符(包括 emoji)的完整编码 |
特点 | 支持代理对,支持 UTF-16 以外字符 |
返回类型 | Number,如果越界则返回 undefined |
对比 | 更现代、更强大,推荐替代 charCodeAt() |
注:——代理对(Surrogate Pair)
总结:
术语 含义 代理对 表示 Unicode 编码超出 BMP(U+FFFF)的字符,需两个 UTF-16 单元 作用 用于支持 emoji、生僻字等字符 示例 "😄"、"𠮷"、"🧠" 判断方式 charCodeAt(0)
返回大于 0xD800,小于 0xDBFF推荐方法 codePointAt()
和fromCodePoint()
支持完整字符处理1.介绍
是一种在 UTF-16 编码中表示超出基本多语言平面(BMP,即 U+0000 到 U+FFFF)字符的方法。
JavaScript 使用 UTF-16 编码存储字符串。
每个字符通常用 2 个字节(16 位)表示。
但有些字符(比如 emoji 😄、生僻字 𠮷)码点超过了 0xFFFF(即 十进制 65535),需要 两个 16 位的单元来表示(即使用两个UTF-16单元编码),这两个单元就叫做 代理对。
2.具体结构
写法顺序: 低位代理项1 高位代理项0
部分 名称 范围(十六进制) 高位代理项 high surrogate——》如 索引0 0xD800
-0xDBFF
低位代理项 low surrogate 0xDC00
-0xDFFF
两者组合后表示一个码点范围在
U+10000 ~ U+10FFFF
的字符。
3. 为何要理解代理对:
js中,场景 误差示例 .length
会把代理对当作两个字符"😄".length === 2
.charAt()
只能访问 UTF-16 单元"😄".charAt(0)
是乱码——》高位乱码.charCodeAt()
只能取 0~65535不能获取完整码点 ✅ .codePointAt()
✅ 可正确处理代理对字符
4. 常用方法对代理对字符的支持情况
方法 是否支持完整字符? charCodeAt()
❌ 不支持,返回 UTF-16 单元 codePointAt()
✅ 支持 fromCharCode()
❌ 不支持 fromCodePoint()
✅ 支持(推荐)
例子:写法顺序: 低位代理项1 高位代理项0
let str = "😄"; // Unicode U+1F604 console.log(str.length); // 2 console.log(str.charCodeAt(0)); // 55357 (0xD83D 高位代理项) console.log(str.charCodeAt(1)); // 56836 (0xDE04 低位代理项)console.log(str.codePointAt(0)); // 128516 (0x1F604 ✅ 正确码点)
codePointAt()
与 charCodeAt()
的区别
比较项 | charCodeAt() | codePointAt() |
---|---|---|
支持范围 | 基本多语言平面(BMP)U+0000 ~ U+FFFF | 支持所有 Unicode,包括辅助平面(如 emoji) |
返回 | UTF-16 编码单元 | Unicode 码点(真正字符编码) |
表情/特殊字符支持 | ❌ 不支持完整字符,不支持 超过 0xFFFF 的字符(emoji、生僻字 | ✅ 支持 |
返回类型 | 十进制整数 | 十进制整数 |
★JS56 返回函数
描述
实现函数 functionFunction,调用之后满足如下条件:
1、返回值为一个函数 f
2、调用返回的函数 f,返回值为按照调用顺序的参数拼接,拼接字符为英文逗号加一个空格,即 ', '
3、所有函数的参数数量为 1,且均为 String 类型
示例1
输入:
functionFunction('Hello')('world')
输出:
Hello, world
解答
法一:闭包保存参数 并按顺序拼接
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><style>/* 填写样式 */</style>
</head><body><!-- 填写标签 --><script type="text/javascript">// 填写JavaScript// 法一:闭包保存参数 并按顺序拼接function functionFunction(str){return f = function(str1){// 以下两种方法都可以。return `${str}, ${str1}`;return str + ", " + str1;}}</script>
</body></html>
法二:★ 函数柯里化实现
// 法一:函数柯里化实现/* */function functionFunction(str){// 字符串拼接function strAdd(){return Array.prototype.join.call(arguments, ', ');}// 柯里化实现function curry(fn, argLength){return function curried(...args){if(args.length >= argLength){return fn.apply(this, args);}else{return function(...args1){return curried.apply(this, args.concat(args1));}}}}return curry(strAdd, 2)(str);}
拓展:两种——无限柯里化实现(但不适用于本题,本题要求两次调用后直接返回字符串)
// 第一种:无限柯里化实现(但不适用于本题,本题要求两次调用后直接返回字符串)function functionFunction(str){const curried = (nextStr) => functionFunction(`${str}, ${nextStr}`);curried.toString = () => str;return curried;}// 第二种:无限次柯里化实现。(适用于functionFunction('xx')('xx')()的情况,有最后一个() 便于判断终止条件)function functionFunction(str) {let result = [str];function f(next){if(typeof next === "string"){result.push(next);return f; // 调用自身,以实现链式调用}else{ // if(typeof next === 'undefined'){return result.join(',');}}return f; // 使得 一开始的functionFunction可以形成链式调用}console.log(functionFunction("Hello")("world")+"");
第二种无限柯里化的图解:
functionFunction("a") → 返回 f↓f("b") → push → 返回 f↓f("c") → push → 返回 f↓f() → next = undefined → join → 返回结果
✅ 总结:三种 return 的作用
return 写法 | 所在位置 | 原因 & 功能 |
---|---|---|
return f; | 内部(字符串时) | 保证函数可以链式调用 |
return result.join(', ') | 内部(终止调用) | 当没有再传入字符串时,输出最终结果 |
return f; | 最外部 functionFunction | 初始化链式调用起点,返回处理函数 f |
知识点
函数柯里化(Currying):curry(目标函数,期望的参数个数)
闭包函数(Closure):函数引用了外部变量。内层函数通过闭包访问外层函数的参数 str
。
链式调用(Chaining):调用自身以实现链式调用。如 f('a')('b')('c')()
🔗 1. 链式调用(Chaining)
连续调用多个方法或函数。常见于 jQuery
、Vue
、Promise
、axios
等库。
✅ 核心:函数 返回自身 或返回另一个函数对象。
例:
class Counter {constructor() {this.count = 0;}add() {this.count++;return this; // 关键:返回自身}log() {console.log(this.count);return this;}
}new Counter().add().add().log(); // 输出 2
🧪 2. 柯里化(Currying)
把一个多参数函数,转换成每次只传一个参数的函数链式调用形式。
✅ 实战意义:
-
预设参数
-
实现函数复用(高阶函数)
例:
function add(a) {return function(b) {return a + b;}
}
add(2)(3); // 5
// 柯里化函数function curry(fn, argLength) {return function curried(...args) {if (args.length >= argLength) {return fn.apply(this, args)} else {return function(...args2) {return curried.apply(this, args.concat(args2))}}}}
🌀 3. 闭包(Closure)
函数访问外部函数作用域的变量,即使外部函数已经返回。
✅ 用途:
-
数据私有化(模拟私有变量)
-
实现记忆缓存
-
异步场景保存上下文
function outer() {let name = "Alice";return function inner() {console.log(name); // 能访问外部变量}
}
const fn = outer();
fn(); // 输出 Alice
链式调用、柯里化、闭包的 联系与区别
知识点 | 说明 |
---|---|
闭包(Closure) | 返回的函数可以访问外层函数的变量。 |
柯里化(Currying) | 把接受多个参数的函数,变成一系列只接收一个参数的函数。 |
链式调用 | 函数返回自身或另一个函数,实现连续调用。 |
apply/call 用法 | 用来改变函数的 this 指向并传递参数。 |
toString / valueOf 重写 | 控制函数在隐式转换时如何被字符串化。 |
特性 | 链式调用 | 柯里化 | 闭包 |
---|---|---|---|
是否返回函数 | ✅ 是 | ✅ 是 | ✅ 是 |
是否依赖作用域变量 | ❌ 否 | ✅ 是(用于参数累积) | ✅ 是(用于记住变量) |
是否用于参数传递 | ✅ 可能 | ✅ 是核心 | ❌ 通常不是主要目的 |
是否支持函数链 | ✅ 是 | ✅ 是(链式传参) | ❌ 通常只返回一次 |
典型写法 | obj.fn1().fn2() | fn(a)(b)(c) |
|