字符串、数字对象
primitive 数据
前面我们学习了 对象和数组。
一个对象(Object)实例数据,比如 {name:'白月黑羽'}
,就是一个对象类型的实例,简称一个对象
一个数组(Array)实例数据,比如 [1,2,3]
,就是一个数组类型的实例,简称一个数组
实际上, Array.prototype 的原型就是 Object.prototype
所以,一个数组数据,它的原型的原型就是 Object.prototype,也可以说是一个对象类型,也可以说是一个对象。
实际上,几乎所有的js数据类型,原型链最终都是 Object.prototype
,所以几乎所有的js数据类型的实例,都可以说是一个 对象
它们都可以使用 Object.prototype
的属性方法,和自身原型的属性方法。
那么我们前面学过的 数字(number)和字符串(string),它们有没有原型呢? 它们是不是对象呢?它们有没有属性和方法呢?
比如下面的 n1,s1
let n1 = 356
let s1 = '您好'
注意:它们是 primitive ( 原语 )数据, 不是对象数据
primitive 数据 没有 属性,底层实现 往往就是 直接对应 存储在内存的 数据
所以非常高效。
primitive数据是不能改变的。
注意:
let n1 = 356
let s1 = '您好'
n1 = 33
s1 = '白月黑羽'
并没有改变原来的 356
和 您好
这两个数据,
而是新建了 33
和 白月黑羽
这两个数据, 让 n1 和 s1 对应这两个新数据。
原来的数据对象没有变量引用,会被js引擎清除掉。
可能有的朋友会说:
不对啊, 前面的教程里就说过,字符串可以有 length
属性,表示长度,还有切片slice方法
var s1 = '你好'
var len = s1.length
既然有属性方法,就不是 primitive,不就是对象吗?
这是因为,js引擎看到这样的代码,
会自动创建一个字符串 封装对象: String
然后调用这个对象的 length属性,就像这样
var len = (new String(s1)).length
所以 s1 变量对应的是一个 字符串 primitive, 而不是对象
如果要定义s1变量 对应一个 字符串对象 ,需要这样写
var s1 = new String("你好");
但是我们不推荐这样做,因为定义为primitive 效率更高。而且 js会自动在需要的时候帮我们产生对象
字符串对象
字符串对象 String 有如下常用的属性方法
length
前面说过, length
属性可以返回字符串对象的长度,也就是包含了多少个字符
'我们今天不去上学,我们去踢足球'.length // 表达式结果是15
indexOf
字符串的 indexOf 方法 和 数组的 indexOf 方法类似,
它用来在字符串中查找 参数字符串,并返回该 参数字符串 在其中 第一个
出现的位置索引
var str1 = '我们今天不去上学,我们去踢足球'
// 返回 0 , str1字符串中有两个 '我们'
// indexOf返回的是第一个 '我们' 的索引 0
var pos1 = str1.indexOf('我们')
如果字符串对象里面 没有
要查找的参数字符串,就会返回 -1
indexOf 方法 的第二个参数,用来指定 查找起始位置
,比如
var str1 = '我们今天不去上学,我们去踢足球'
// 第2个参数 5, 表示从 索引 5 的位置开始往后查找
var pos1 = str1.indexOf('我们',5)
// 返回的是后面 我们 的索引 9
console.log(pos1)
切片 slice
在前面讲数组的切片时讲过
split
js 中的 split 方法 和 Python 中的 字符串 split 方法类似,
split 是我们常用的方法,经常用来从字符串中 截取 出我们想要的信息。
split 方法以参数字符串为分割符 ,将字符串 切割为多个 字符串,作为元素存入一个数组,并返回这个数组。
看看下面的例子
var str1 = '小张:79 | 小李:88 | 小赵:83'
var pos1 = str1.split('|')
这里 split方法指定用 |
作为源字符串str1的分割符, 这样 原来的字符串 就被分成了 3个部分
小张:79
小李:88
小赵:83
最红将这个三个字符串存入一个数组(数组)中返回,返回的结果就是
[
'小张:79 ',
' 小李:88 ',
' 小赵:83'
]
大家要注意,分隔符本身在切割后,会被丢弃掉,所以切割后的字符串中不会有分隔符。
可能有的读者会注意到上面的3个字符串不对齐,
这不是我们的笔误。
原来的字符串,被切开后,分隔符前面有的空格字符,会保留下来。
小张
前面没有空格,所以切割后,切割出来的结果就没有空格。
而 小李
和 小赵
前面是有空格的,切割出来的结果就有空格
不一定非要用 竖线分割, 我们可以指定任何其他的分隔符来分割字符串,比如
'小张:79 | 小李:88 | 小赵:83'.split('小赵')
这样就是以 小赵 这个字符串为界 ,分割。返回结果如下
[
'小张:79 | 小李:88 | ',
':83'
]
trim、trimStart、trimEnd
trim
方法可以 删除 字符串前面和后面的空白字符,比如空格、tab符, 以及行终结符, 比如回车、换行等等
但是不会删除字符串中间的空白字符。
比如
' 小 李:88 '.trim()
返回的就是 '小 李:88',去掉了前后的空格,但是中间的空格不会去掉
trimStart
方法 将 字符串前面 (左边) 的空格删除,但是不会删除字符串中间和右边的空格
比如
' 小 李:88 '.trimStart()
返回的就是 '小 李:88 '
trimEnd
方法 将 字符串后面 (右边) 的空格删除,但是不会删除字符串中间和左边的空格
比如
' 小 李:88 '.trimEnd()
返回的就是 ' 小 李:88'
替换
replace 也是常用的方法,用来 替换 字符串里面 第一个 指定的 子字符串 为另一个 字符串
比如
var str1 = '我们今天不去上学,我们去踢足球';
var str2 = str1.replace('我们', '他们') ;
注意:是返回值为新的替换后的字符串, 原来的字符串并不会改变
str2 结果就是 '他们今天不去上学,我们去踢足球'
发现了吗? 只有第一个我们被替换,后面的我们没被替换。
js 字符串对象的 replace 方法只 替换第一个 匹配。 和Python不同。
如果想要 替换所有匹配,可以使用先 split 再 join 的方法,像这样
var str1 = '我们今天不去上学,我们去踢足球';
var str2 = str1.split('我们').join('他们');
新版本的浏览器 支持 replaceAll
方法。
replaceAll 方法,用来 替换 字符串里面 所有指定的 子字符串 为另一个 字符串
比如
var str1 = '我们今天不去上学,我们去踢足球'
var str2 = str1.replaceAll('我们', '他们')
上面的 replaceAll
方法就会把字符串中所有的我们,替换成他们
startsWith 和 endsWith
startsWith
方法检查字符串是否以参数指定的字符串 开头,如果是,返回true,否则返回false
endsWith
方法检查字符串是否以指定的字符串 结尾,如果是,返回true,否则返回false
var str1 = '我们今天不去上学,我们去踢足球'
str1.startsWith('我们') // 返回 true
str1.endsWith('我们') // 返回 false
字符串模板
前面学过字符串的拼接,比如
var salary = 20000
// 计算出缴税额,存入变量tax
var tax = salary *25/100
// 计算出税后薪资,存入变量aftertax
var aftertax = salary*75/100
console.log(
'税前薪资是:' + salary + '元, 缴税:' + tax + '元, 税后薪资是:' + aftertax + '元'
)
字符串的多次拼接比较麻烦,一不小心就可能 漏掉了 一个加号或者引号。
如果我们能够这样写一个模板
税前薪资是 x 元, 缴税:y 元, 税后薪资是:z 元
然后,直接将我们计算好的 税前薪资, 缴税额,税后薪资 分别作为 x, y, z 填入进去。
这样就不需要麻烦的字符串拼接了。
js 支持这样的 字符串模板
操作
就是在字符串使用 反引号
,然后占位符使用 ${}
,里面直接放入对应的数据对象。
如下所示
`税前薪资是:${salary}元, 缴税:${tax}元, 税后薪资是:${aftertax}元`
运行一下,可以发现输出结果一样。
这种方式是不是更加的直观明了呢?
转义符
我们在代码中定义一个字符串的时候,有些字符是比较特殊的。
比如 换行符, 我们可以用 回车键
敲出来。
var a = `abcd
efg`
其中abcd 和efg之间其实就是有一个 换行字符
。
有时候像这样的字符出现在字符串中,可以使用转义写法来表示,比如上的字符串就等价于
var a = 'abcd\nefg'
console.log(a)
\n
就是一个转义字符,表示一个换行字符。
除了 \n
,还有一些其他的字符可以用转义符表示
比如我们还可以
用 \t
表示tab字符,
a = 'abcd\tefg'
console.log(a)
用 \x41
表示 ASCII编码为0x41的字符(也就是字符 A
,后面字符编码会学习到 )
a = 'abcd\x41efg'
console.log(a)
用 \u767d
表示 unicode编码为0x768d的字符(也就是汉字 白
,后面字符编码会学习到 )
a = 'abcd\u767defg'
console.log(a)
js字符串中 转义字符都是用反斜杠 \
开头 。
如果字符串中本身需要有反斜杠,并非转义,比如Windows下面的路径
var path = 'c:\windows\temp'
console.log(path)
其中的 \t
会被当做一个tab字符,而不是 \ 和 t 两个字符。
这时,可以在在前面再加一个反斜杠, 像下面这样
path = 'c:\\windows\\temp'
console.log(path)
也可以 使用反引号
,在字符前面加上一个 String.raw
,表示字符串内容是raw string, 无需转义,像这样
path = String.raw`c:\windows\temp`
console.log(path)
这种写法术语叫 Tagged template literals
数字对象
数字对象Number 有如下常用的属性方法
parseInt、parseFloat
可以使用 Number 的 parseInt
方法,把字符串表示的数字转化为 整数,
可以使用 Number 的 parseFloat
方法,把字符串表示的数字转化为 数字(整数或小数),
Number.parseInt('34') // 返回 34
Number.parseInt('34.4') // 还是返回 34
Number.parseFloat('34') // 返回 34
Number.parseFloat('34.4') // 返回 34.4
js 的全局函数 parseInt 就是 Number.parseInt ,
parseFloat 就是 Number.parseFloat
所以可以更简单
parseInt('34') // 返回 34
parseInt('34.4') // 还是返回 34
parseFloat('34') // 返回 34
parseFloat('34.4') // 返回 34.4
toString
可以使用 Number 的 toString 方法,把字符串表示的数字转化为 整数,
var num = 4545
console.log(num.toString())
// 直接调用数字的方法,需要加括号
(23423.44).toString()