字符串的扩展

news2024/9/21 4:35:14

字符串解读

es6加强了对Unicode 的支持,允许\uxxxx的形式展现一个字符,例如:

console.log('\u0061'); // 打印 a

\u后面的为字符的 Unicode 码点 \u 后面4位 xxxx

但是这种写法只识别 \u0000\UFFFF 之间的字符,超出需要使用两个双字节表示,例如:

console.log('\uD842\uDFB7'); // 打印 吉

如果说超出了\uxxxx字节的范围,则为两个字节的拼接,例如:

console.log('\u20BB7'); // 输出 ' 7'   \u20BB系统识别为空
console.log('\u00617'); // 输出 'a7'   

\u0061识别为a,由于7超出了这个字节,所以为\u0061+7,结果为a7

es6Unicode 的支持进行了加强,如果超出了两个字节,放入大括号内即可正常解读

console.log("\u{20BB7}"); // 打印 吉

// 只要将码点放入大括号即可正确解读
console.log('\u{41}\u{42}\u{43}'); // 输出ABC

大括号与双字节的写法是等价的

  console.log('\u{1F680}' == '\uD83D\uDE80'); // 大括号与4字节的写法等价 输出true

js对字符的几种表现方法:

console.log('\z' === 'z');
console.log('\172' === 'z');
console.log('\x7A' === 'z');
console.log('\u007A' === 'z');
console.log('\u{7A}' === 'z');
console.log('z' === 'z');

字符串的遍历

字符串遍历for...of

  for (let codePoint of 'foo') {
     console.log(codePoint); // f o o
   }

其实一般的遍历,例如for,也可以遍历字符串,但是for无法识别大于0xFFFF的码点,而for...of则可以识别

 let text = String.fromCodePoint(0x20BB7)
 
 // for循环
    for (let i = 0; i < text.length; i++) {
         console.log(text[i]); // ' ' 空
      }
      
// for---of可以识别 大于0xFFFF的码点 , 而传统的for无法识别
    for (let i of text) {
        console.log(i); // 吉
     }

有些时候,我们在用JSON.stringify转字符串的时候,发现转译的字符串多了几个\
根据标准,JSON数据必须是 UTF-8 编码。但是JSON.stringify()方法有可能返回不符合 UTF-8 标准的字符串。
UTF-8 标准规定,0xD8000xDFFF之间的码点,不能单独使用,必须配对使用。比如,\uD834\uDF06是两个码点,但是必须放在一起配对使用,代表字符𝌆。这是为了表示码点大于0xFFFF的字符的一种变通方法。单独使用\uD834\uDF06这两个码点是不合法的,或者颠倒顺序也不行,因为\uDF06\uD834并没有对应的字符。
JSON.stringify()的问题在于,它可能返回0xD8000xDFFF之间的单个码点。

JSON.stringify('\u{D834}') // "\u{D834}"

所以 es2019JSON.stringify()做出了改变,如果遇到0xD8000xDFFF之间的单个码点,或者不存在的配对形式,它会返回转义字符串,留给应用自己决定下一步的处理。

console.log(JSON.stringify('\u{D834}')) // ""\\uD834""
console.log(JSON.stringify('\uDF06\uD834')) // ""\\uD834""

模板字符串

1、模板字符串识别标签,并却可以识别多行内容,传统的写法需要用+ 号连接,
2、模板字符串识别空格

let context = document.getElementById('context')
let str = `<div>东方 不败</div>
           <div>东方求败</div>`
console.log(context.innerHTML = str); // 页面显示 东方 不败

在这里插入图片描述
传统的字符串插值,需要使用"字符"+100+"值"的形式,用 + 拼接,值是不能嵌套在引号当中的,否则会解译为字符串。

console.log("<div>东方不败有" + 100 + "元</div>")

模板字符串直接使用${xxx}即可在字符串中插值,并且在里面可以使用表达式以及调用函数。

let str2 = `<div>东方不败${100}</div>` // 东方不败 100

// 表达式
let s = 100
let str3 = `<div>东方不败${s == 100 ? '有100元' : '没有100元'}</div>` // 东方不败有100元

// 调用函数
let str4 = `<div>调用函数:${text2()}</div>`
function text2() {
            return '东方不败'
        }
let context2 = document.getElementById('context2')
console.log(context2.innerHTML = str4); // 页面显示 调用函数:东方不败  

模板字符串可以嵌套使用,此处用的是map遍历结构,需要注意的是,forEach是无法在此遍历结构的,会直接报错,因为forEach会改变原数组,而map则不会(数组为基础类型时原数组不变)。

let context3 = document.getElementById('context3')
let arr = [{
            name: '字符串',
            index: '01'
        }, {
            name: '字符串',
            index: '02'
        }]
let s2 = `
        <div>模板字符串嵌套:${
        arr.map(el => `
                <div>${el.name}</div>
                <div>${el.index}</div>
            `)
       }</div>
       `
        context3.innerHTML = s2

结果:
在这里插入图片描述


标签模板

函数名跟上模板字符串,则为标签模板,左边是函数,右边实际上是函数参数,例如:

alert `hello` // 等同于 alert(['hello'])

此处的alert是函数,紧跟在后面的模板字符串就是它的参数,这里会触发alert弹框,展示hello
但如果模板字符串有变量,就不是简单的调用,而是会先将模板字符串先处理成多个参数,再调用函数,例如:

let a = 5
let b = 10
// alert `hello ${ a + b} , word ${ a * b }`
tag(`hello ${ a + b} , word ${ a * b }`)

此处的tag等同于 tag([hello ', ', word ', ''],15,50),在这里,模板字符串前有一个tag,这个tag是一个函数,整个表达式的返回值就是tag函数处理模板字符串后返回的值,返回结果可以看上面alert打印的内容。
实际上是将tag转换成了:

 // 实际上转换成了
function tag(stringArr, value1, value2) {
       // ......
 }
// 或者
function tag(stringArr, ...values) {
      console.log(stringArr, values);
      // ......
 }

1、tag函数的第一个参数是一个数组,整个数组是模板字符串中没有变量替换的部分。
2、变量的替换,只发生在数组的第一个成员于第二个成员之间,第二个成员与第三个成员之间,以此类推。
3、tag函数的其他参数,都是模板字符串各个变量被替换后的值。这里的模板字符串有两个参数,所以这里会接收 value1 value2 两个参数。
例如:
第一个参数:[hello ', ', word ', '']
第二个参数:15
第三个参数:50
其实也就是 tag([hello ', ', word ', ''],15,50)

这里再举一个例子:
下面就是关于标签模板是怎样将字符串与值拼接的过程,最终展现的就是标签模板编译后的结果

let total = 30;   // 变量
let msg = passthru `The total is ${total} (${total*1.05} with tax)`;

function passthru(literals) {
//literals : ['The total is ', ' (', ' with tax)', raw: Array(3)]
     let result = ''
     let i = 0
     while (i < literals.length) {
          result += literals[i++];
          if (i < arguments.length) {
          /* arguments:
          0:['The total is ', ' (', ' with tax)', raw: Array(3)]
          1 : 30
          2 : 31.5
          */
     console.log(arguments); // 参数的数组  
     result += arguments[i]
           }
        }
      return result
   }

输出结果:The total is 30 (31.5 with tax)
步骤拆解:
1: passthru函数的参数literals就是标签模板的参数['The total is ', ' (', ' with tax)', raw: Array(3)]
2: while 遍历了数组参数的长度,并且在内部进行判断
3: if中的arguments就是参数的数组,这一步就是关键的字符串与值得拼接,拼接的步骤如下:

while遍历,如果参数为true则循环遍历,直到false终止
遍历内容如下:
   The total is 
   30
   (
   31.5

前面说过了:变量的替换,只发生在数组的第一个成员于第二个成员之间,第二个成员与第三个成员之间,以此类推。所以此处也是这样处理的,最后返回的结果就是The total is 30 (31.5 with tax)

恶意输入

标签模板还有一个重要的作用就是防止用户恶意输入,如果用户在输入框恶意嵌套标签是非常不安全的行为。

let sender = '<script>alert("恶意代码")</cript>'

function SaferHTML(templateData) {
        let s = templateData[0]
        for (let i = 1; i < arguments.length; i++) {
             let arg = String(arguments[i])
             s +=arg.replace(/&/g,"&amp")
                    .replace(/</g,"&lt")
                    .replace( />/g,"&gt") 
     // 过滤 转义 &为&amp字符;  <为&lt字符;  >为&gt字符;
             s += templateData[i]
            }
            return s
        }

此处将用户嵌套的script标签进行了转译,&为&amp字符<为&lt字符>为&gt字符

let message = SaferHTML `<p>${sender}个人信息</p>`
console.log(message);
// 打印 <p>&lt;script&gt;alert("恶意代码")&lt;/script&gt; 个人信息</p>

由于我的编译器会自动格式化,所以用 sxxxcript 代替 script
在这里插入图片描述


标签模板可以做多语言转(国际化)

i18n `Welcome to ${userName}, you are visitor number ${visitorNumber}!`

甚至可以在标签模板嵌套其他语言

jsx `
   <div>
      <input
       ref='input'
       onChange='${this.handleChange}'
       defaultValue='${this.state.value}' />
       ${this.state.value}
       </div>
 `
// 此处就是通过jsx函数,将DOM字符串转换为React对象

模板处理函数的第一个参数,也就是非参数的模板字符串数组,有一个raw属性

 console.log(`abc`) // ['abc',row:Array[1]]
// 这个raw保存的是转义后的原字符串

在这里插入图片描述
这个数组后面的raw保存的是转义后的原字符串。


案例源码:https://gitee.com/wang_fan_w/es6-science-institute

如果觉得这篇文章对你有帮助,欢迎点亮一下star

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/61850.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第十七章 管理组件库的pull request

一个好的项目很少会由一个人来独立完成。即使你完成了所有功能实现&#xff0c;也需要有人给你 Review 和提建议、找 Bug。比如添加新的组件、完善文档、添加单元测试、提出改进意见。 这节课我们就介绍一下如何参与开源社区的代码贡献。对于任何一个开源项目&#xff0c;我们…

map容器/multimap容器

目录 1.map基本概念 简介 本质 优点 map和multimap区别 2.map构造和赋值 功能描述: 函数原型 3.map大小和交换 功能描述 函数原型 4 map插入和删除 功能描述 函数原型 5. map查找和统计 功能描述 函数原型 6 map容器排序 学习目标 主要技术点 1.map基本概念…

web入门-爆破

文章目录web21web22web23python脚本php脚本web24web25web26web27web28web21 进入网站&#xff0c;提示要登陆&#xff0c;妥爆破 抓包 注意到最下行的base64编码 发现就是刚刚输入的账号密码 因此这里就是要选择爆破的地方了 发给inruder&#xff0c;添加爆破位 载入题目给…

【坚持不懈的每日一题——力扣篇】1774. 最接近目标价格的甜点成本(中等)-- dfs / dp

GitHub同步更新&#xff08;已分类&#xff09;&#xff1a;Data_Structure_And_Algorithm-Review 公众号&#xff1a;URLeisure 的复习仓库 公众号二维码见文末 以下是本篇文章正文内容&#xff0c;下面案例可供参考。 一、题目描述 力扣今天推的每日一题是道中等题 。 示例…

qt人员管理模块(模块化程序)功能块复制直接使用不冲突

一、前言 qt对人员管理部分个人总结的模块化程序&#xff0c;直接按照步骤复制粘贴程序&#xff0c;直接实现人员管理功能&#xff0c;无需花费脑筋在理清各个思路&#xff0c;适合快速编写组装程序 二、环境 windows qt5.7 sqlite3 三、正文 思来想去大半天&#xff0c;…

JS快速入门

一、JS介绍 JavaScript &#xff08;简称JS&#xff09;&#xff0c;是一门跨平台、面向对象的脚本语言&#xff08;弱类型语言&#xff09;&#xff0c;而Java语言也是跨平台的、面向对象的语言&#xff0c;只不过Java是编译语言&#xff0c;是需要编译成字节码文件才能运行的…

自定义RBAC(1)

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e; 在对Spring Security稍做了解之后&#xff0c;可以知道&#xff0c;Spring Security其实只是一个实现认证授权的框架&#xff0c;封装了很多实现细节。但也有一些…

【Linux网络编程】服务端编程初体验

文章目录前言服务端是啥、有什么特点核心函数socket的简介服务器编程客户端代码The End前言 在上节课(Linux网络编程初体验)中我们实现了连接bilibili的功能&#xff0c;并获取其html源码 如图所示. 今天我们要自己编写个服务端来服务我们的客户端 提示&#xff1a;以下是本篇…

SGI STL 二级空间配置源码刨析

文章目录内存分配第二级配置器空闲链表的设计内存申请代码内存释放代码注意内存分配 当我们new一个对象时&#xff0c;实际做了两件事情&#xff1a; 使用malloc申请了一块内存。执行构造函数。 在SGI中&#xff0c;这两步独立出了两个函数&#xff1a;allocate申请内存&…

年产20吨鸡枞菌产品的生产工艺设计(lunwen+课题登记表+cad图纸)

目录 摘 要 1 Abstract 2 一、设计任务和内容 4 1.1 设计题目 4 1.2 设计原始数据 4 二、设计说明 5 2.1 全厂总平面布置 5 2.1.1 原料厂及堆场 5 2.1.2 生产区 5 2.1.3 厂前区 6 2.1.4 动力区 6 2.1.5 辅助车间 6 2.1.6 仓库区 6 2.2 三废的处理及回收 6 2.3 车间布置说明 6 三…

Request和Response基础知识入门

文章目录1&#xff0c;Request和Response的概述2&#xff0c;Request对象2.1 Request继承体系2.2 Request获取请求数据2.2.1 获取请求行数据2.2.2 获取请求头数据2.2.3 获取请求体数据2.2.4 获取请求参数的通用方式2.3 IDEA快速创建Servlet2.4 请求参数中文乱码问题2.4.1 POST请…

【Unity3D】绘制物体表面三角形网格

1 仅绘制三角形网格 1&#xff09;创建游戏对象 创建一个空对象&#xff0c;重命名为 Grid&#xff0c;并在其下添加需要绘制网格的对象&#xff0c;如下&#xff1a; 场景显示如下&#xff1a; 2&#xff09;添加脚本组件 GridController.cs using System; using UnityEngin…

JavaWeb_第4章_RequestResponse

JavaWeb_第4章_Request&Response 文章目录JavaWeb_第4章_Request&Response1&#xff0c;Request和Response的概述2&#xff0c;Request对象2.1 Request继承体系2.2 Request获取请求数据2.2.1 获取请求行数据2.2.2 获取请求头数据2.2.3 获取请求体数据2.2.4 获取请求参数…

【ceph】分布式存储ceph

1 块存储&#xff0c;文件存储&#xff0c;对象存储 1.1 简介 文件存储&#xff1a;分层次存储&#xff0c;文件存储在文件夹中&#xff1b;访问文件时系统需要知道文件所在的路径。 举例&#xff1a;企业部门之间运用网络存储器&#xff08;NAS&#xff09;进行文件共享。 …

把握出租车行驶的数据脉搏 :出租车轨迹数据给你答案!

城市化带来的道路拥堵、出行耗时长等交通问题给交管部门带来了巨大的挑战。 ▼ 通过安装在出租车上的GPS设备&#xff0c;可以采集到大量的轨迹数据&#xff0c;从而帮助我们分析人们出行信息&#xff0c;达到优化交通的目的。 最近我们被客户要求撰写关于出租车行驶的研究报…

一次性分清zip、gzip、bzip2、tar命令

文章目录归类zip与unzip命令tar命令使用方式zipunzipgzipgunzipbzip2bunzip2tar归类 我们把这几个命令归类为几种能力&#xff0c;一个是解压缩能力一个是打拆包能力。 我这里打包的意思是不使用压缩算法对文件进行压缩&#xff0c;只是简单的把多个文件归档为一个文件。而拆包…

Qt OpenGL(二十五)——Qt OpenGL 核心模式-Qt封装的函数实现彩色三角形

Qt OpenGL(二十五)——Qt OpenGL 核心模式-Qt封装的函数实现彩色三角形 上一篇文章我们绘制了彩色的三角形,接下来其实就应该是让这个三角形旋转起来了,但是,旋转起来之前,还是想通过Qt自己的封装类实现彩色的三角形,并且让他旋转起来。 这才我(冯一川)是写这个系列…

编程之美4 Nim游戏

Tag&#xff1a;贪心&#xff1b;动态规划 题目 N块石头排成一行&#xff0c;每块石头有各自固定的位置。两个玩家依次取石头&#xff0c;每个玩家每次可以取其中任意一块石头&#xff0c;或者相邻的两块石头&#xff0c;石头在游戏过程中不能移位&#xff08;即编号不会改变…

在ASF中使用On Demand生产DEM等产品时使用不同参考DEM的区别

在ASF中使用On Dmand生产DEM等产品时使用不同参考DEM 主要有两种DEM&#xff0c;分别是SRTM和COP-DEM&#xff08;GLO-30&#xff09; 当我们添加Dmand进程之后&#xff0c;点击On Demand Queue 然后进入On Demand界面&#xff08;如下图所示&#xff09; 在Processing Op…

MySQL主从复制介绍及实操演示

1. 基本概念 MySQL主从复制的主要效果简单来说是将两个单独的数据库服务器关联起来&#xff0c;对于主机&#xff08;Master&#xff09;以及从机&#xff08;Slave&#xff09;&#xff0c;从机的数据会伴随着主机数据的变化而同步 2. 主从复制作用 可以解决单个MySQL数据库…