年纪大了记性不好(其实是脑子不好使,但又不想承认),有些东西总是容易忘,所以为了便于之后查看干脆记下来,用自己的语言再把一些概念整理一下,都是自己写的,以后再看这些文字也会有亲切感(好像很有道理的亚子)~

基本类型:String、Boolean、Number、Undefined、Null、Symbol、BigInt

引用类型:Object

下面我会详细说一下其中七种数据类型(不包括 BigInt)中可能你不太知道的一些细节。

1. String储存结构

计算机是以二进制存储以及发送接收数据的。二进制的 1位,也叫做 1bit 。它是计算机内部存储的最基本的单位。

计算机只能处理数字js判断字符串是否包含某个字符,如果想要处理文本,必须将文本转换为数字才能处理,在计算机中 1bit 能表示2个状态(0或1),1Byte 等于 8bit,所以 1Byte 能表示 2^8 – 1 个整数,也就是255个。如果想表示更大的数字,就需要更多的字节数,比如 2Byte 能表示 2^16 – 1 ,也就是 65535个整数。最早只有127个字符被编码到计算机里,也就是大小写英文字母、数字和一些其他字符,这个编码表就是 ASCII 表。

但如果要表示中文,那么 1Byte 显然是不够的,至少需要 2Byte ,所以中国制定了 GB2312 编码,但每个国家如果都制定一个自己的编码表,那么就没办法正确显示多语言混合的文本。为了解决这个问题,Unicode 编码应运而生。它把所有语言统一到一个编码里,采用 2Byte 表示一个字符,即最多可以表示 2^16 – 1 ,也就是 65535 个字符。这样基本上可以覆盖世界上常用的文字,如果要表示更多的文字,也可以采用 4Byte 进行编码,这是一种通用的编码规范 。

JS 中的字符也采用Unicode编码,也就是js中的中英文字符都占用 2Byte(16bit)大小。

在 JS 中的二进制数据储存中,二进制前三位为 100 代表字符串

基本包装类型

在 js 中,只有引用类型才有属性或者方法,基本类型理论上没有属性或方法,而字符串又属于基本类型,但为什么字符串能调用一些属性和方法呢?

原因是 js 为了方便对字符串进行操作,ECMA 提供了一个基本包装类型 String对象。它是一种特殊的引用类型, 当 js 引擎需要读取或操作一个字符串时,他会在内部创建一个 String类型的包装对象实例,然后调用这个实例的属性或方法并返回结果后,再立即清除这个实例。

这也是为什么 字符串明明是一个基本类型 却能调用属性和方法的原因。

几个Unicode问题总结基本概念

Unicode 是目前最常见的字符编码,它用一个码位映射一个字符。在 js 中,Unicode 码位范围为 ‘u{0000}’ ~ ‘u{10ffff}’ ,可以表示超过110万个字符。格式为 ‘u{十六进制数字}’

console.log('u{0041}'// 'A'
console.log('u{0061}'// 'a'
console.log('I u{2661} Hagan'// 'I ♡ Hagan'
console.log('u{20bb7}'// ''

Unicode 最前面的 65536 个字符位称为 基本多文种平面,它的码位范围为 ‘u{0000}’ ~ ‘u{ffff}’ ,最常见的字符都放在这个平面上。

剩下的字符都放在 辅助平面 上,码位范围为 ‘u{010000}’ ~ ‘u{10ffff}’

判断是否为辅助平面的方法为十六进制数字的位数是否超过4位。

字符串长度问题

解决代理对长度问题

在内部,JavaScript 将辅助平面内的字符表示为代理对,并将单独的代理对分开为单独的 “字符”,所以代理对的length属性可能与我们的预期不一致,比如:

const str = 'u{20BB7}'
console.log(str) // ''
console.log(str.length) // 2

而我们想获取的长度应该为 1,这里可以使用以下方法正确获取长度

const str = 'u{20BB7}'
console.log(Array.from(str).length) // 1

解决组合标记长度问题

u{0307} 表示 q̣̇ 上面的点, u{0323} 表示 q̣̇ 下面的点,这三个字符共同组成了一个 q̣̇ ,如下代码

const str = 'qu{0307}u{0323}'
console.log(str) // `q̣̇`
console.log(str.length) // 3

我们期待拿到的长度应该为1,可实际拿到的length为3,这里可以使用以下方法获取长度

const str = 'qu{0307}u{0323}'

const regex = /(P{Mark})(p{Mark}+)/gu
const trim = str.replace(regex, ($0, $1, $2) => $1)
console.log(Array.from(str).length) // 1

将以上代码封装起来,可封装成以下方法

注意:此方法无法处理表情字符序列组合 ‘‍‍‍’

const getStringLength = function (string{
  const regex = /(P{Mark})(p{Mark}+)/gu
  const str = string.replace(regex, ($0, $1, $2) => $1)
  return Array.from(str).length
}

export default getStringLength

字符串反转

注意:此方法无法正确处理组合标记

const getReverseString = function (string{
  return Array.from(string).reverse().join('')
}

export default getReverseString

一位名叫 Missy Elliot 的聪明的计算机科学家提出了一个防弹算法来解决组合标记问题

根据码位获取字符串

注意:此方法无法正确处理组合标记

String.fromCodePoint(0x20bb7// ''

根据字符串获取码位

注意:此方法无法正确处理组合标记

''.codePointAt().toString(16// 20bb7

遍历字符串

注意:此方法无法正确处理组合标记

for (const item of '') {
  console.log(item) // ''
}

Number储存结构

js采用 IEEE754 标准中的 双精度浮点数来表示一个数字,标准规定双精度浮点数采用 64 位存储js判断字符串是否包含某个字符,即 8 个字节表示一个浮点数。存储结构如下图:

在双精度浮点数中,第一位的 1bit符号位 决定了这个数的正负,指数部分的 11bit 决定数值大小,小数部分的 52bit 决定数值精度。

在 JS 中的二进制数据储存中,二进制前三位为 010 代表双精度数字

数值范围

指数部分为 11bit 也就是 2^11 – 1 = 2047,取中间值进行偏移得到 [-1023, 1024],因此这种存储结构能够表示的数值范围为 2^-1023 至 2^1024,超出这个范围无法表示。转换为科学计数法为:

2^-1023 = 5 × 10^-324

2^1024 = 1.7976931348623157 × 10^308

Number.MAX_VALUE // 1.7976931348623157e+308
Number.MIN_VALUE // 5e-324

安全整数

IEEE754 规定,有效数字第一位默认总是1,但它不保存在 64 位浮点数之中。所以有效数字为 52bit + 1 = 53bit。

这意味着js能表示并进行精确算术运算的安全整数范围为 [-2^53 -1, 2^53 – 1] 即 -9007199254740991 到最大值 9007199254740991 之间的范围。

Math.pow(253) - 1 // 9007199254740991
-Math.pow(253) - 1 // -9007199254740991

可以通过 Number.MAX_SAFE_INTEGER 和 Number.MIN_SAFE_INTEGER 来分别获取安全整数最大值和最小值。

console.log(Number.MAX_SAFE_INTEGER) // 9007199254740991
console.log(Number.MIN_SAFE_INTEGER) // -9007199254740991

对于超过这个安全整数的运算,需要使用 BigInt 来计算。

console.log(9007199254740991 + 2// 9007199254740992
console.log(BigInt(9007199254740991) + BigInt(2)) // 9007199254740993n

精度丢失

计算机中的数字都是用二进制储存的,如果要计算 0.1 + 0.2 那么计算机会分别把 0.1 和 0.2 转成二进制,然后相加,最后把相加的结果转为10进制。

但有一些浮点数转化为二进制时会出现无限循环,比如 0.1

0.0001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 10001 无限循环

而上面我们说过计算机能储存的小数位最多只有 53 位,为了尽可能的接近目标值,所以采用类似十进制四舍五入的方法,在二进制中 0舍1入,最终 0.1 储存到计算机中成为以下数值。

0.0001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 101

0.1 转换成科学技术法

(−1)^0 × 2^(-4) × (1.1001100110011001100110011001100110011001100110011010)2

0.2 科学技术法表示为

(−1)^0 × 2^(-3) × (1.1001100110011001100110011001100110011001100110011010)2

在浮点数做加法时要先进行对位操作,将较小的指数转化为较大的指数,并将小数部分右移

(−1)^0 × 2^(-3) × (0.111001100110011001100110011001100110011001100110011010)2

(−1)^0 × 2^(-3) × (1.1001100110011001100110011001100110011001100110011010)2

最终 0.1 + 0.2 在计算机中的计算过程如下

计算后 0.1 + 0.2 的结果为

(−1)^0 × 2^(−2) × (1.0011001100110011001100110011001100110011001100110100)2

然后通过 js 将二进制转为10进制

(-1)**0 * 2**-2 * (0b10011001100110011001100110011001100110011001100110100 * 2**-52) === 0.30000000000000004 // true
console.log(0.1 + 0.2) ; // 0.30000000000000004

这就是经典的 0.30000000000000004 问题,0.1 和 0.2 在转换为二进制时由于做了 0舍1入 ,发生了一次精度丢失,而对于计算后的二进制又 做了一次 0舍1入 发生一次精度丢失,因此得到的结果是不准确的。

解决办法:

精度丢失解决办法就是先将小数转换成整数,然后用整数进行计算得到结果后再转换为小数,用 js 封装方法如下

math.js

// 判断number是否为一个整数
const isInteger = function (number{
  return Math.floor(number) === number
}

// 四舍五入
const toFixed = function (number, decimalLength = 0{
  var times = Math.pow(10, decimalLength)
  var fixed = number * times + 0.5
  return parseInt(fixed) / times
}

// 将一个浮点数转成整数,返回整数和倍数
const toInteger = function (floatNumber{
  const numberInfo = { times1number0 }
  const isNegative = floatNumber < 0
  if (isInteger(floatNumber)) {
    numberInfo.number = floatNumber
    return numberInfo
  }
  const stringFloatNumber = String(floatNumber)
  const dotPosition = stringFloatNumber.indexOf('.')
  const length = stringFloatNumber.substr(dotPosition + 1).length
  numberInfo.times = Math.pow(10, length)
  numberInfo.number = toFixed(Math.abs(floatNumber) * numberInfo.times)
  if (isNegative) numberInfo.number = -numberInfo.number
  return numberInfo
}

// 加
export const add = function (number1, number2, decimalLength = 0{
  const { number: num1, times: times1 } = toInteger(number1)
  const { number: num2, times: times2 } = toInteger(number2)
  const maxTimes = Math.max(times1, times2)
  let result
  if (times1 === times2) result = (num1 + num2) / maxTimes
  if (times1 > times2) result = (num1 + num2 * (times1 / times2)) / maxTimes
  if (times1 < times2) result = (num1 * (times2 / times1) + num2) / maxTimes
  return toFixed(result, decimalLength)
}

import { add } from './math.js'
console.log(add(0.10.21)) // 0.3

特殊数值变量

JavaScript 提供了几个特殊数值,用于判断数字的边界和其他特性

Number.MAX_VALUE // JavaScript 中的最大值
Number.MIN_VALUE // JavaScript 中的最小值
Number.MAX_SAFE_INTEGER // 最大安全整数,为 2^53 - 1
Number.MIN_SAFE_INTEGER // 最小安全整数,为 -(2^53 - 1)
Number.POSITIVE_INFINITY // 对应 Infinity,代表正无穷
Number.NEGATIVE_INFINITY // 对应 -Infinity,代表负无穷
Number.EPSILON // 是一个极小的值,用于检测计算结果是否在误差范围内
Number.NaN // 表示非数字,NaN与任何值都不相等,包括NaN本身
Infinity // 表示无穷大,分 正无穷 Infinity 和 负无穷 -Infinity

四舍五入

有时我们需要对一些数字进行四舍五入,而这些数字可能包含小数

Math.round(number) 方法无法对小数进行计算

Number.toFixed() 方法实际上采用四舍六入五成双的规则实现,存在一些缺陷,具体可看一下这篇文章

以上两个方法有时候无法满足我们的需求,所以封装以下方法

math.js

// 四舍五入
export const toFixed = function (number, decimalLength = 0{
  var times = Math.pow(10, decimalLength)
  var fixed = number * times + 0.5
  return parseInt(fixed) / times
}

import { toFixed } from './math.js'

toFixed(0.22862986837463// 0.229

Boolean储存结构

在 JS 中的二进制数据储存中,二进制前三位为 110 代表布尔值

基本概念

Boolean 只有两个类型,true、false。在js中所有类型的值都能转换成 Boolean 值。如下代码

Boolean(''// false // 除了空字符串意外,其他字符串都为true
Boolean(0 || NaN// false // 除了0与NaN,其他数字都为true
Boolean(undefined// false
Boolean(Symbol()) // true
Boolean(null// false
Boolean({} && []) // true // 所有引用类型都为true

隐式类型转换

当使用以下操作符获取 Boolean 结果时,在过程中 js 内部会先进行隐式类型转换,再使用转换后的结果进行对比,最终确定为 true、 false。

> >=

限时特惠:本站每日持续更新海量设计资源,一年会员只需29.9元,全站资源免费下载
站长微信:ziyuanshu688

js判断字符串是否包含_js 正则判断是否包含_js判断字符串是否包含某个字符

前言

熟悉我的朋友可能会知道,我一向是不写热点的。为什么不写呢?是因为我不关注热点吗?其实也不是。有些事件我还是很关注的,也确实有不少想法和观点。但我一直奉行一个原则,就是:要做有生命力的内容。

对于前端工程师来说, 正则表达式也许是javascript语言中最晦涩难懂的, 但是也往往是最简洁的.工作中遇到的很多问题,诸如搜索,查找, 高亮关键字等都可以使用正则轻松解决,所以有句话说的好:

正则用的好, 加班远离我.

今天笔者就复盘一下javascript正则表达式的一些使用技巧和高级API, 并通过几个实际的案例,来展现正则表达式的魅力.如果大家觉得正则表达式理解起来很麻烦,也可以使用如下在线网站, 只需要输入你的正则表达式, 它就能以图形的方式将你的正则展示出来:

js判断字符串是否包含某个字符_js判断字符串是否包含_js 正则判断是否包含

你将收获正文

对于正则的基本用法笔者这里就不总结了,这里重点介绍一些比较有用且难懂的知识点.在最后笔者会写10个经典的正则案例, 供大家学习参考, 或者在工作中直接使用.

js判断字符串是否包含_js 正则判断是否包含_js判断字符串是否包含某个字符

以上几点应用笔者在下文中会写几个例子来讲解.

模式匹配的用法(x)

模式匹配主要用来匹配某一类字符串并记住匹配项.

案例:

let str = 'xuxi is xuxi is'
let reg = /(xuxi) (is) 1 2/g
reg.test(str) // true (1)
str.replace(reg, '$1 $2') // xuxi is (2)

复制代码

解释: 其中括号被称为捕获括号, 模式中的 1 和 2 表示第一个和第二个被捕获括号匹配的子字符串,即 xuxi 和 is,匹配了原字符串中的后两个单词, 因此(1)中运行的结果为true. 当我们在字符串中使用replace时, 我们可以使用$1, $2这样的方式获取第n个匹配项,并用来替换字符串. 如(2)中的运行结果.

非捕获括号的模式匹配(?:x)

主要用来匹配某一类字符串但不记住匹配项.

案例:

let str = 'xuxixuxi'
let reg = /(?:xuxi){1,2}/g
reg.test(str) // true (1)

复制代码

js判断字符串是否包含某个字符_js 正则判断是否包含_js判断字符串是否包含

解释: 其中(?:)被称为非捕获括号, 我们可以使用它匹配一组字符但是并不记住该字符,一般用来判断某类字符是否存在于某字符串中.

先行断言x(?=y)

先行断言: 匹配’x’仅仅当’x’后面跟着’y’.

案例:

let str = '王者融化'
let reg = /王(?=者)/
reg.test(str) // true (1)

复制代码

解释: /王(?=者)/会匹配到”王”仅当它后面跟着”者”.但是”者”不属于匹配结果的一部分.

后行断言(?

反向否定查找: 仅仅当’x’前面不是’y’时匹配’x’.

案例:

let str = '3.1415'
let reg = /(?<!.)d+/
reg.exec(str) // [3] (1)

复制代码

解释: /(?字符集合和反向字符集合的用法 [xyz] / [^xyz]

[xyz]: 一个字符集合。匹配方括号中的任意字符js判断字符串是否包含某个字符,包括转义序列。你可以使用破折号(-)来指定一个字符范围。

[^xyz]: 一个反向字符集。也就是说,它匹配任何没有包含在方括号中的字符。你可以使用破折号(-)来指定一个字符范围。任何普通字符在这里都是起作用的

案例:

let str = 'abcd'
let reg1 = /[a-c]+/
let reg2 = /[^d]$/
reg1.test(str) // true (1)
reg2.test(str) // false (2)

复制代码

js判断字符串是否包含某个字符_js判断字符串是否包含_js 正则判断是否包含

解释: (1)中将返回true因为字符串中包含a-c中的字符, (2)中奖返回false, 因为字符串结尾为d, 但正则reg2需要匹配结尾不为d的字符串.

词边界和非单词边界匹配bB

b 匹配一个词的边界。一个词的边界就是一个词不被另外一个“字”字符跟随的位置或者前面跟其他“字”字符的位置,例如在字母和空格之间。注意,匹配中不包括匹配的字边界。换句话说,一个匹配的词的边界的内容的长度是0。

B 匹配一个非单词边界。匹配如下几种情况:(1)字符串第一个字符为非“字”字符 (2)字符串最后一个字符为非“字”字符 (3)两个单词字符之间 (4)两个非单词字符之间 (5)空字符串

案例:

let str = 'xuxi'
let reg1 = /xib/
let reg2 = /xuB/
reg1.exec(str) // [xi] (1)
reg2.exec(str) // [xu] (2)

复制代码

解释: (1)中匹配到了单词边界,即xi, 为该字符串的末尾.(2)中应为xu为非单词边界,所以会被其匹配到.

空白字符/非空白字符匹配sS

s: 匹配一个空白字符,包括空格、制表符、换页符和换行符.

S: 匹配一个非空白字符

案例:

let str = 'xuxi is'
let reg1 = /.*s/g
let reg2 = /Sw*/g
reg1.exec(str) // [xuxi] (1)
reg2.exec(str) // [xuxi] (2)

复制代码

js判断字符串是否包含某个字符_js判断字符串是否包含_js 正则判断是否包含

js 正则判断是否包含_js判断字符串是否包含某个字符_js判断字符串是否包含

解释: (1)和(2)中执行之后都将匹配xuxi, 一个是空白字符之前的匹配, 一个是非空白字符的匹配.

单字字符/非单字字符匹配w/W

w: 匹配一个单字字符(字母、数字或者下划线)。等价于 [A-Za-z0-9_]。

W: 匹配一个非单字字符。等价于 [^A-Za-z0-9_]

由于以上2种模式比较简单,这里就不一一介绍了.

正则10大应用案例

接下来笔者将总结几个使用正则的实际应用,供大家学习和参考.

1. 去除字符串内指定元素的标签

function trimTag(tagName, htmlStr) {
let reg = new RegExp(`<${tagName}(\s.*)*>(\n|.)*<\/${tagName}>`, "g")
return htmlStr.replace(reg, '')
}

复制代码

2. 短横线命名转驼峰命名

// 短横线转驼峰命名, flag = 0为小驼峰, 1为大驼峰
function toCamelCase(str, flag = 0) {
if(flag) {
return str[0].toUpperCase() + str.slice(1).replace(/-(w)/g, ($0, $1) => $1.toUpperCase())
}else {
return str.replace(/-(w)/g, ($0, $1) => $1.toUpperCase())
}
}

复制代码

3. 实现一个简单的模板引擎

关于实现一个模板引擎, 实现中用到了大量的正则,建议感兴趣的可以直接看实现一个简单的模板引擎.

4. 去除字符串中的空格符

function trimAll(str) {
return str.replace(/s*/g,"")
}

复制代码

5. 判断指定格式的数据输入合法性

function numCheck(str, specialNum) {
if(str.indexOf(',') > -1) {
return str.splite(',').every(item=>this.numCheck(item));
} else {
return str.split(specialNum).length === 2;
}
}

复制代码

6. 去除url参数字符串中值为空的字段

// 去除url参数字符串中值为空的字段
const trimParmas = (parmaStr:string = '') => {
return parmaStr.replace(/((w*?)=&|(&w*?=)$)/g, '')
}

复制代码

7. 将浏览器参数字符串转化为参数对象

function unParams(params = '?a=1&b=2&c=3') {
let obj = {}
params && params.replace(/((w*)=([.a-z0-9A-Z]*)?)?/g, (m,a,b,c) => {
if(b || c) obj[b] = c
})
return obj
}

复制代码

8. 计算字符串字节数

/**
* 计算字符串字节数
* @param str
* @desc 一个中文占2个字节, 一个英文占一个字节
*/

function computeStringByte(str) {
let size = 0,
strArr = str.split(''),
reg = /[u4e00-u9fa5]/ // 判断是否为中文
for(let i = strArr.length; i--; i>=0) {
if(reg.test(strArr[i])) {
size+= 2
}else {
size += 1
}
}
return size
}

复制代码

9. 匹配是否包含中文字符

function hasCn(str) {
let reg = /[u4e00-u9fa5]/g
return reg.test(str)
}

复制代码

10. 实现搜索联想功能

function searchLink(keyword) {
// 模拟后端返回数据
let list = ['abc', 'ab', 'a', 'bcd', 'edf', 'abd'];
let reg = new RegExp(keyword, 'i');
return list.filter(item => reg.test(item))
}

复制代码

最后

如果想学习更多H5游戏,webpack,node,gulpjs判断字符串是否包含某个字符,css3,javascript,nodeJS,canvas数据可视化等前端知识和实战,欢迎在公号《趣谈前端》加入我们的技术群一起学习讨论,共同探索前端的边界。

限时特惠:本站每日持续更新海量设计资源,一年会员只需29.9元,全站资源免费下载
站长微信:ziyuanshu688

字符串作为基本的信息交流的桥梁,几乎被所有的编程语言所实现

多数开发者几乎每天都在和字符串打交道

JavaScript通过自动装箱字符串字面量为String对象,更加简化了字符串的使用

字符串作为基本的信息交流的桥梁,几乎被所有的编程语言所实现(然而c、c++没有提供)。

多数开发者几乎每天都在和字符串打交道,语言内置的String模块,极大地提升了开发者的效率。

JavaScript通过自动装箱字符串字面量为String对象,自然地继承了String.prototype的所有方法,更加简化了字符串的使用。

截止ES6,字符串共包含31个标准的API方法,其中有些方法出镜率较高,需要摸透原理;有些方法之间相似度较高js判断字符串是否包含某个字符,需要仔细分辨;甚至有些方法执行效率较低,应当尽量少的使用。下面将从String构造器方法说起,逐步帮助你掌握字符串。

String构造器方法

fromCharCode

fromCharCode()方法返回使用指定的Unicode序列创建的字符串,也就是说传入Unicode序列,返回基于此创建的字符串。

语法:fromCharCode(num1, num2,…),传入的参数均为数字。

如下这是一个简单的例子,将返回 ABC、abc、*、+、- 和 /:

String.fromCharCode(65, 66, 67); // "ABC"
String.fromCharCode(97, 98, 99); // "abc"
String.fromCharCode(42); // "*"
String.fromCharCode(43); // "+"
String.fromCharCode(45); // "-"
String.fromCharCode(47); // "/"

看起来fromCharCode像是满足了需求,但实际上由于js语言设计时的先天不足(只能处理UCS-2编码,即所有字符都是2个字节,无法处理4字节字符),通过该方法并不能返回一个4字节的字符,为了弥补这个缺陷,ES6新增了fromCodePoint方法,请往下看。

fromCodePoint(ES6)

fromCodePoint()方法基于ECMAScript 2015(ES6)规范,作用和语法同fromCharCode方法,该方法主要扩展了对4字节字符的支持。

// "" 是一个4字节字符,我们先看下它的数字形式
"".codePointAt(); // 119558
//调用fromCharCode解析之,返回乱码
String.fromCharCode(119558); // "팆"
//调用fromCodePoint解析之,正常解析
String.fromCodePoint(119558); // ""

除了扩展对4字节的支持外,fromCodePoint还规范了错误处理,只要是无效的Unicode编码,就会抛出错误RangeError: Invalid code point…,这就意味着,只要不是符合Unicode字符范围的正整数(Unicode最多可容纳1114112个码位),均会抛出错误。

String.fromCodePoint('abc'); // RangeError: Invalid code point NaN
String.fromCodePoint(Infinity); // RangeError: Invalid code point Infinity
String.fromCodePoint(-1.23); // RangeError: Invalid code point -1.23

注:进一步了解Unicode编码,推荐这篇文章:浅谈文字编码和Unicode(下):

如需在老的浏览器中使用该方法,请参考Polyfill

#Polyfill-浏览器补丁。

raw(ES6)

raw() 方法基于ECMAScript 2015(ES6)规范,它是一个模板字符串的标签函数,作用类似于Python的r和C#的@字符串前缀,都是用来获取一个模板字符串的原始字面量。

语法:

String.raw(callSite, …substitutions),callSite即模板字符串的“调用点对象”,…substitutions表示任意个内插表达式对应的值,这里理解起来相当拗口,下面我将通俗的讲解它。

如下是python的字符串前缀r:

# 防止特殊字符串被转义
print r'anbtc' # 打印出来依然是 "anbtc"
# python中常用于正则表达式
regExp = r'(?<=123)[a-z]+'

如下是String.raw作为前缀的用法:

// 防止特殊字符串被转义
String.raw`anbtc`; // 输出为 "anbtc"
// 支持内插表达式
let name = "louis";
String.raw`Hello n ${name}`;  // "Hello n louis"
// 内插表达式还可以运算
String.raw`1+2=${1+2},2*3=${2*3}`; // "1+2=3,2*3=6"

String.raw作为函数来调用的场景不太多,如下是用法:

// 对象的raw属性值为字符串时,从第二个参数起,它们分别被插入到下标为0,1,2,...n的元素后面
String.raw({raw: 'abcd'}, 1, 2, 3); // "a1b2c3d"
// 对象的raw属性值为数组时,从第二个参数起,它们分别被插入到数组下标为0,1,2,...n的元素后面
String.raw({raw: ['a', 'b', 'c', 'd']}, 1, 2, 3); // "a1b2c3d"

那么怎么解释String.raw函数按照下标挨个去插入的特性呢?MDN上有段描述如下:

In most cases, String.raw() is used with template strings. The first syntax mentioned above is only rarely used, because the JavaScript engine will call this with proper arguments for you, just like with other tag functions.

这意味着,String.raw作为函数调用时,基本与ES6的tag标签模板一样。如下:

// 如下是tag函数的实现
function tag(){
  const array = arguments[0];
  return array.reduce((p, v, i) => p + (arguments[i] || '') + v);
}
// 回顾一个simple的tag标签模板
tag`Hello ${ 2 + 3 } world ${ 2 * 3 }`; // "Hello 5 world 6"
// 其实就想当于如下调用
tag(['Hello ', ' world ', ''], 5, 6); // "Hello 5 world 6"

因此String.raw作为函数调用时,不论对象的raw属性值是字符串还是数组,插槽都是天生的,下标为0,1,2,…n的元素后面都是插槽(不包括最后一个元素)。实际上,它相当于是这样的tag函数:

function tag(){
  const array = arguments[0].raw;
  if(array === undefined || array === null){ // 这里可简写成 array == undefined
    throw new TypeError('Cannot convert undefined or null to object');
  }
  return array.reduce((p, v, i) => p + (arguments[i] || '') + v);
}

实际上,String.raw作为函数调用时,若第一个参数不是一个符合标准格式的对象,执行将抛出TypeError错误。

String.raw({123: 'abcd'}, 1, 2, 3); // TypeError: Cannot convert undefined or null to object

目前只有Chrome v41+和Firefox v34+版本浏览器实现了该方法。

String.prototype

和其他所有对象一样,字符串实例的所有方法均来自String.prototype。以下是它的属性特性:

writable

js 正则判断是否包含_js判断字符串是否包含某个字符_js判断字符是否中文

false

enumerable

false

configurable

false

可见,字符串属性不可编辑,任何试图改变它属性的行为都将抛出错误。

属性

String.prototype共有两个属性,如下:

String.prototype.constructor指向构造器(String())

String.prototype.length表示字符串长度

方法

字符串原型方法分为两种,一种是html无关的方法,一种是html有关的方法。

我们先看第一种。但是无论字符串方法如何厉害,都不至于强大到可以改变原字符串。

HTML无关的方法

常用的方法有,charAt、charCodeAt、concat、indexOf、lastIndexOf、localeCompare、match、replace、search、slice、split、substr、substring、toLocaleLowerCase、toLocaleUpperCase、toLowerCase、toString、toUpperCase、trim、valueof等ES5支持的,以及 codePointAt、contains、endsWith、normalize、repeat、startsWith等ES6支持的,还包括quote、toSource、trimLeft、trimRight等非标准的。

接下来我们将对各个方法分别举例阐述其用法。若没有特别说明,默认该方法兼容所有目前主流浏览器。

charAt

charAt()方法返回字符串中指定位置的字符。

语法:str.charAt(index)

index为字符串索引(取值从0至length-1),如果超出该范围,则返回空串。

console.log("Hello, World".charAt(8)); // o, 返回下标为8的字符串o

charCodeAt

charCodeAt()返回指定索引处字符的Unicode数值。

语法:str.charCodeAt(index)

index 为一个从0至length-1的整数。如果不是一个数值,则默认为0,如果小于0或者大于字符串长度,则返回NaN。

Unicode编码单元(code points)的范围从0到1,114,111。开头的128个Unicode编码单元和ASCII字符编码一样。

charCodeAt()总是返回一个小于65,536的值。因为高位编码单元需要由一对字符来表示,为了查看其编码的完成字符,需要查看charCodeAt(i)以及charCodeAt(i+1)的值。如需更多了解请参考:

fixedCharCodeAt()。

console.log("Hello, World".charCodeAt(8)); // 111
console.log("前端工程师".charCodeAt(2)); // 24037, 可见也可以查看中文Unicode编码

concat

concat()方法将一个或多个字符串拼接在一起,组成新的字符串并返回。

语法:str.concat(string2, string3, …)

console.log("早".concat("上","好")); // 早上好

但是concat的性能表现不佳,强烈推荐使用赋值操作符(+或+=)代替 concat。”+” 操作符大概快了concat几十倍。(数据参考性能测试)。

indexOf

lastIndexOf

indexOf()方法用于查找子字符串在字符串中首次出现的位置,没有则返回-1。该方法严格区分大小写,并且从左往右查找。而lastIndexOf则从右往左查找,其它与前者一致。

语法:

str.indexOf(searchValue[,fromIndex=0])

str.lastIndexOf(searchValue [, fromIndex=0])

searchValue表示被查找的字符串,fromIndex表示开始查找的位置,默认为0,如果小于0,则查找整个字符串,若超过字符串长度,则该方法返回-1,除非被查找的是空字符串,此时返回字符串长度。

console.log("".indexOf("",100)); // 0
console.log("IT改变世界".indexOf("世界")); // 4
console.log("IT改变世界".lastIndexOf("世界")); // 4

locateCompare

locateCompare()方法用来比较字符串,如果指定字符串在原字符串的前面则返回负数,否则返回正数或0,其中0表示两个字符串相同。该方法实现依赖具体的本地实现,不同的语言下可能有不同的返回。

语法:str.localeCompare(str2 [, locales [, options]])

var str = "apple";
var str2 = "orange";
console.log(str.localeCompare(str2)); // -1
console.log(str.localeCompare("123")); // 1

目前Safari浏览器暂不支持该方法,但Chrome v24+、Firefox v29+,IE11+ 和 Opera v15+都已实现了它。

match

match()方法用于测试字符串是否支持指定正则表达式的规则,即使传入的是非正则表达式对象,它也会隐式地使用new RegExp(obj)将其转换为正则表达式对象。

语法:str.match(regexp)

该方法返回包含匹配结果的数组,如果没有匹配项,则返回 null。

描述

若正则表达式没有g标志,则返回同RegExp.exec(str) 相同的结果。而且返回的数组拥有一个额外的input属性,该属性包含原始字符串,另外该数组还拥有一个index属性,该属性表示匹配字符串在原字符串中索引(从0开始)。

若正则表达式包含g标志,则该方法返回一个包含所有匹配结果的数组,没有匹配到则返回null。

相关 RegExp 方法

若需测试字符串是否匹配正则,请参考 RegExp.test(str)

若只需第一个匹配结果,请参考RegExp.exec(str)

var str = "World Internet Conference";
console.log(str.match(/[a-d]/i)); // ["d", index: 4, input: "World Internet Conference"]
console.log(str.match(/[a-d]/gi)); // ["d", "C", "c"]
// RegExp 方法如下
console.log(/[a-d]/gi.test(str)); // true
console.log(/[a-d]/gi.exec(str)); // ["d", index: 4, input: "World Internet Conference"]

由上可知,RegExp.test(str)方法只要匹配到了一个字符也返回true。

而RegExp.exec(str)方法无论正则中有没有包含g标志,RegExp.exec将直接返回第一个匹配结果,且该结果同str.match(regexp)方法不包含g标志时的返回一致。

replace

该方法在之前已经讲过,详细请参考String.prototype.replace高阶技能()。

search

search()方法用于测试字符串对象是否包含某个正则匹配,相当于正则表达式的test方法,且该方法比match()方法更快。

如果匹配成功,search()返回正则表达式在字符串中首次匹配项的索引,否则返回-1。

注意:search方法与indexOf方法作用基本一致,都是查询到了就返回子串第一次出现的下标,否则返回-1,唯一的区别就在于search默认会将子串转化为正则表达式形式,而indexOf不做此处理,也不能处理正则。

语法:str.search(regexp)

var str = "abcdefg";
console.log(str.search(/[d-g]/)); // 3, 匹配到子串"defg",而d在原字符串中的索引为3

search()方法不支持全局匹配(正则中包含g参数),如下:

console.log(str.search(/[d-g]/g)); // 3, 与无g参数时,返回相同

slice

slice()方法提取字符串的一部分,并返回新的字符串。该方法有些类似Array.prototype.slice方法。

语法:str.slice(start, end)

首先end参数可选,start可取正值,也可取负值。

取正值时表示从索引为start的位置截取到end的位置(不包括end所在位置的字符,如果end省略则截取到字符串末尾)。

取负值时表示从索引为length+start位置截取到end所在位置的字符。

var str = "It is our choices that show what we truly are, far more than our abilities.";
console.log(str.slice(0,-30)); // It is our choices that show what we truly are
console.log(str.slice(-30)); // , far more than our abilities.

split

split()方法把原字符串分割成子字符串组成数组,并返回该数组。

语法:str.split(separator, limit)

两个参数均是可选的,其中separator表示分隔符,它可以是字符串也可以是正则表达式。

如果忽略separator,则返回的数组包含一个由原字符串组成的元素。如果separator是一个空串,则str将会被分割成一个由原字符串中字符组成的数组。limit表示从返回的数组中截取前limit个元素,从而限定返回的数组长度。

var str = "today is a sunny day";
console.log(str.split()); // ["today is a sunny day"]
console.log(str.split("")); // ["t", "o", "d", "a", "y", " ", "i", "s", " ", "a", " ", "s", "u", "n", "n", "y", " ", "d", "a", "y"]
console.log(str.split(" ")); // ["today", "is", "a", "sunny", "day"]

使用limit限定返回的数组大小,如下:

console.log(str.split(" ")); // ["today"]

使用正则分隔符

(RegExp separator)

如下:

console.log(str.split(/s*iss*/)); // ["today", "a sunny day"]

若正则分隔符里包含捕获括号,则括号匹配的结果将会包含在返回的数组中。

console.log(str.split(/(s*iss*)/)); // ["today", " is ", "a sunny day"]

substr

substr()方法返回字符串指定位置开始的指定数量的字符。

语法:str.substr(start[, length])

start表示开始截取字符的位置,可取正值或负值。取正值时表示start位置的索引,取负值时表示length+start位置的索引。

length 表示截取的字符长度。

var str = "Yesterday is history. Tomorrow is mystery. But today is a gift.";
console.log(str.substr(47)); // today is a gift.
console.log(str.substr(-16)); // today is a gift.

目前Microsoft’s JScript不支持start参数取负的索引,如需在IE下支持,请参考Polyfill(#Description)。

substring

substring()方法返回字符串两个索引之间的子串。

语法:

str.substring(indexA[, indexB])

indexA、indexB表示字符串索引,其中indexB可选,如果省略,则表示返回从indexA到字符串末尾的子串。

描述

substring要截取的是从indexA到indexB(不包含)之间的字符,符合以下规律:

若indexA ==indexB,则返回一个空字符串;

若省略indexB,则提取字符一直到字符串末尾;

若任一参数小于0或NaNjs判断字符串是否包含某个字符,则被当作0;

若任一参数大于length,则被当作length。

而如果indexA>indexB,则substring的执行效果就像是两个参数调换一般。比如:

str.substring(0, 1) == str.substring(1, 0)

var str = "Get outside every day. Miracles are waiting everywhere.";
console.log(str.substring(1,1)); // ""
console.log(str.substring(0)); // Get outside every day. Miracles are waiting everywhere.
console.log(str.substring(-1)); // Get outside every day. Miracles are waiting everywhere.
console.log(str.substring(0,100)); // Get outside every day. Miracles are waiting everywhere.
console.log(str.substring(22,NaN)); // Get outside every day.

toLocaleLowerCase

toLocaleUpperCase

toLocaleLowerCase()方法返回调用该方法的字符串被转换成小写的值,转换规则根据本地化的大小写映射。而

toLocaleUpperCase()方法则是转换成大写的值。

语法:

str.toLocaleLowerCase(), str.toLocaleUpperCase()

console.log('ABCDEFG'.toLocaleLowerCase()); // abcdefg
console.log('abcdefg'.toLocaleUpperCase()); // ABCDEFG

toLowerCase

toUpperCase

这两个方法分别表示将字符串转换为相应的小写,大写形式,并返回。如下:

console.log('ABCDEFG'.toLowerCase()); // abcdefg
console.log('abcdefg'.toUpperCase()); // ABCDEFG

toString

valueOf

这两个方法都是返回字符串本身。

js 正则判断是否包含_js判断字符是否中文_js判断字符串是否包含某个字符

语法:str.toString(), str.valueOf()

var str = "abc";
console.log(str.toString()); // abc
console.log(str.toString()==str.valueOf()); // true

对于对象而言,toString和valueOf也是非常的相似,它们之间有着细微的差别,请尝试运行以下一段代码:

var x = {
    toString: function () { return "test"; },
    valueOf: function () { return 123; }
};
console.log(x); // test
console.log("x=" + x); // "x=123"
console.log(x + "=x"); // "123=x"
console.log(x + "1"); // 1231
console.log(x + 1); // 124
console.log(["x=", x].join("")); // "x=test"

当“+”操作符一边为数字时,对象x趋向于转换为数字,表达式会优先调用valueOf方法,如果调用数组的join 方法,对象x趋向于转换为字符串,表达式会优先调用toString方法。

trim

trim()方法清除字符串首尾的空白并返回。

语法:str.trim()

console.log(" a b c ".trim()); // "a b c"

trim()方法是ECMAScript 5.1标准加入的,它并不支持IE9以下的低版本IE浏览器,如需支持,请参考以下兼容写法:

if(!String.prototype.trim) {
  String.prototype.trim = function () {
    return this.replace(/^s+|s+$/g,'');
  };
}

codePointAt(ES6)

codePointAt()方法基于ECMAScript 2015(ES6规范,返回使用UTF-16编码的给定位置的值的非负整数。

语法:str.codePointAt(position)

console.log("a".codePointAt(0)); // 97
console.log("u4f60u597d".codePointAt(0)); // 20320

如需在老的浏览器中使用该方法,请参考

Polyfill(#Polyfill)。

includes(ES6)

includes()方法基于ECMAScript 2015(ES6)规范,它用来判断一个字符串是否属于另一个字符。如果是,则返回true,否则返回false。

语法:str.includes(subString [, position])

subString表示要搜索的字符串,position表示从当前字符串的哪个位置开始搜索字符串,默认值为0。

var str = "Practice makes perfect.";
console.log(str.includes("perfect")); // true
console.log(str.includes("perfect",100)); // false

实际上,Firefox 18-39中该方法的名称为contains,由于bug 1102219:

的存在,它被重命名为includes()。目前只有Chrome v41+和Firefox v40+版本浏览器实现了它,如需在其它版本浏览器中使用该方法,请参考 Polyfill:

#填充

endsWith(ES6)

endsWith()方法基于ECMAScript 2015(ES6)规范,它基本与contains()功能相同,不同的是,它用来判断一个字符串是否是原字符串的结尾。若是则返回true,否则返回false。

语法:str.endsWith(substring [, position])

与contains方法不同,position参数的默认值为字符串长度。

var str = "Learn and live.";
console.log(str.endsWith("live.")); // true
console.log(str.endsWith("Learn",5)); // true

同样目前只有Firefox v17+版本实现了该方法。其它浏览器请参考 Polyfill:

#Polyfill

normalize(ES6)

normalize()方法基于ECMAScript 2015(ES6)规范,它会按照指定的Unicode正规形式将原字符串正规化。

语法:str.normalize([form])

form参数可省略,目前有四种Unicode正规形式,

即“NFC”、”NFD”、”NFKC”以及“NFKD”,

form的默认值为“NFC”。如果form传入了非法的参数值,则会抛出RangeError错误。

var str = "u4f60u597d";
console.log(str.normalize()); // 你好
console.log(str.normalize("NFC")); // 你好
console.log(str.normalize("NFD")); // 你好
console.log(str.normalize("NFKC")); // 你好
console.log(str.normalize("NFKD")); // 你好

目前只有Chrome v34+和Firefox v31+实现了它。

repeat(ES6)

repeat()方法基于ECMAScript 2015(ES6)规范,它返回重复原字符串多次的新字符串。

js判断字符是否中文_js判断字符串是否包含某个字符_js 正则判断是否包含

语法:str.repeat(count)

count参数只能取大于等于0的数字。若该数字不为整数,将自动转换为整数形式,若为负数或者其他值将报错。

var str = "A still tongue makes a wise head.";
console.log(str.repeat(0)); // ""
console.log(str.repeat(1)); // A still tongue makes a wise head.
console.log(str.repeat(1.5)); // A still tongue makes a wise head.
console.log(str.repeat(-1)); // RangeError:Invalid count value

目前只有Chrome v41+、Firefox v24+和Safari v9+版本浏览器实现了该方法。其他浏览器请参考Polyfill:

#填充

startsWith(ES6)

startsWith()方法基于ECMAScript 2015(ES6)规范,它用来判断当前字符串是否是以给定字符串开始的,若是则返回true,否则返回false。

语法:

str.startsWith(subString [, position])

var str = "Where there is a will, there is a way.";
console.log(str.startsWith("Where")); // true
console.log(str.startsWith("there",6)); // true

目前以下版本浏览器实现了该方法,其他浏览器请参考

Polyfill(#Polyfill)。

Chrome

Firefox

Edge

Opera

Safari

41+

17+

28+

9+

其它非标准的方法暂时不作介绍,如需了解请参考

String.prototype()中标注为感叹号的方法。

HTML有关的方法

常用的方法有anchor,link其它方法如big、blink、bold、fixed、fontcolor、fontsize、italics、small、strike、sub、sup均已废除。

接下来我们将介绍anchor和link两个方法,其他废除方法不作介绍。

anchor

anchor()方法创建一个锚标签。

语法:str.anchor(name)

name指定被创建的a标签的name属性,使用该方法创建的锚点,将会成为document.anchors数组的元素。

var str = "this is a anchor tag";
document.body.innerHTML = document.body.innerHTML + str.anchor("anchor1"); // body末尾将会追加这些内容 this is a anchor tag

link

link()方法同样创建一个a标签。

语法:str.link(url)

url指定被创建的a标签的href属性,如果url中包含特殊字符,将自动进行编码。例如”会被转义为&quot。使用该方法创建的a标签,将会成为document.links数组中的元素。

var str = "百度";
document.write(str.link("https://www.baidu.com")); // 百度

小结

部分字符串方法之间存在很大的相似性,要注意区分他们的功能和使用场景。如:

substr和substring,都是两个参数,作用基本相同,两者第一个参数含义相同,但用法不同,前者可为负数,后者值为负数或者非整数时将隐式转换为0。

前者第二个参数表示截取字符串的长度,后者第二个参数表示截取字符串的下标;同时substring第一个参数大于第二个参数时,执行结果同位置调换后的结果。

search方法与indexOf方法作用基本一致,都是查询到了就返回子串第一次出现的下标,否则返回-1,唯一的区别就在于search默认会将子串转化为正则表达式形式,而indexOf不做此处理,也不能处理正则。

另外,还记得吗?concat方法由于效率问题,不推荐使用。

通常,字符串中,常用的方法就charAt、indexOf、lastIndexOf、match、replace、search、slice、split、substr、substring、toLowerCase、toUpperCase、trim、valueof等这些。熟悉它们的语法规则就能熟练地驾驭字符串。

限时特惠:本站每日持续更新海量设计资源,一年会员只需29.9元,全站资源免费下载
站长微信:ziyuanshu688