JavaScript终极面试题之字符串:“105”大于“44”吗,“123b”转Number为多少,slice、substring、substr可以传负数吗等等

前言

String是JavaScript中基本变量之一,也有着比较特殊的性质,其变量不可更改。对象的创建有两种方式:非对象,例var x=“Bill”;对象,例var y = new String(“Bill”)。采用非对象的方式创建字符串时,栈中存放着指针,指向String池中的常量;采用对象的方式创建时,栈中存放着指针,指向堆中的String对象。
注意:不要频繁的对一个字符串变量进行增删替换等操作,因为String为不可更改变量,其增删替换等操作实质是屡次对象的创建和销毁,频繁操作影响性能。

一、字符串的比较

1.相等比较

var x = "Bill";             
var y = new String("Bill");
var z = "Bill";
x == y // true
x === y // false
x === z // true

非对象的字符串比较String常量池中的值,对象字符串比较的是指针地址。
另外创建字符串变量时请不要使用new来创建,它会拖慢执行速度

2.大小比较

字符串之间比较是先依次取字符串的ASCII码,再判断ASCII码先大的即为大。字符转ascii码:用charCodeAt();ascii码砖字符:用fromCharCode();

"105" > "44" // false
"1" > "0987" // true
"1.00004a" > "1.00004b" // false
"absffz" > "absffA" // true

从第一个字符的ASCII码开始比较,如果无法比判断,则比较第二个,以此类推。
大写字母A 到Z 的值是从65 到90,小写a到z 是从91 到 122
具体每个字符的码戳☞这里
字符串和数字的比较可☞参考这篇

实例:当日期类型格式一样时,可以直接比较字符串格式的大小来判断日期的大小,例如: “2020-05-01” > “2020-04-02”

二、字符串转Number

提供五种方式:Number()、parseInt()、parseFloat()、new Number()、* | / 1
建议用* | / 1自动隐式转换为数字格式,效率最好,不建议用new Number()对象的创建方式,效率最低

var a = "123.01"
var b = "123.01abc"
var c = "a123.01bc"
var d = "abc123"
Number(a) // 123.01
Number(b) // NaN 
Number(c) // NaN
Number(d) // NaN
parseInt(a) // 123
parseInt(b) // 123
parseInt(c) // NaN
parseInt(d) // NaN
parseFloat(a) // 123.01
parseFloat(a) // 123.01
parseFloat(a) // NaN
parseFloat(a)// NaN

Number(" 123 ") // 123
parseInt(" 123 ") // 123
parseFloat(" 123  ") // 123
// * | /
a*1 , a/1 // 和Number结果一致

总结: Number会把带有非空非数字的字符转为NaN,parseInt、parseFloat会一次解析字符遇到非空非数字转为NaN,与之不同的是会截取前面数字的值。* | / 1和Number结果一样。

三、字符串相加减

1.相加

"ab" + "b" // abb
"ab" + "cd" // abcd

2.相减

"ab" - "b" // NaN
"ab" - "cd" // NaN
"123" - "12" // 111

带有非字符串的相加减可☞参考这篇

四、字符串截取、替换等常见操作场景

1. 场景一、截取

(1) slice

语法: stringObject.slice(start,end)
start 要抽取的片断的起始下标。如果是负数,则该参数规定的是从字符串的尾部开始算起的位置。也就是说,-1 指字符串的最后一个字符,-2 指倒数第二个字符,以此类推。
end 紧接着要抽取的片段的结尾的下标。若未指定此参数,则要提取的子串包括 start 到原字符串结尾的字符串。如果该参数是负数,那么它规定的是从字符串的尾部开始算起的位置。

// 正数
"abcd".slice(0) //"abcd"
"abcd".slice() //"abcd"
"abcd".slice(1,5) //"bcd"
"abcd".slice(5,1) //""
// 负数时从右向左数数
//start=-1从d开始,最后一位,end接受正数大于0,或者不传,其他为空
"abcd".slice(-1) // "d"
"abcd".slice(-1,1) //"d"
"abcd".slice(-1,2) //"d"
"abcd".slice(-1,-1) // "" 
"abcd".slice(-1,-2) // ""
//start=-3从b开始,end接受负数>=-2正数大于1,其他为空
"abcd".slice(-3,-2) // "b"
"abcd".slice(-3,-1) // "bc"
"abcd".slice(-3,2) // "b"
"abcd".slice(-3,3) // "bc"
//start=1从b开始,end接受负数>=-2正数大于1,其他为空(和上面的例子原理一样)
"abcd".slice(1,-2) // "b"
"abcd".slice(1,-1) // "bc"
"abcd".slice(1,2) // "b"
"abcd".slice(1,3) // "bc"

说明:
slice() 方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。
String 对象的方法 slice()、substring() 和 substr() (不建议使用)都可返回字符串的指定部分。slice() 比 substring() 要灵活一些,因为它允许使用负数作为参数。slice() 与 substr() 有所不同,因为它用两个字符的位置来指定子串,而 substr() 则用字符位置和长度来指定子串。
还要注意的是,String.slice() 与 Array.slice() 相似。

(2)substring

语法: stringObject.substring(start,stop)
start 必需。一个非负的整数,规定要提取的子串的第一个字符在 stringObject 中的位置。发现负数相当于传0,没意义。
stop
可选。一个非负的整数,比要提取的子串的最后一个字符在 stringObject 中的位置多 1。
如果省略该参数,那么返回的子串会一直到字符串的结尾。发现负数相当于传0,没意义。

// 正数
"abcd".substring(0) //"abcd"
"abcd".substring() //"abcd"
"abcd".substring(1,5) //"bcd"
"abcd".substring(1,2) // "b"
"abcd".substring(5,1) //"bcd"
"abcd".substring(4,2) //"cd"
// 传负数时不报错,但结果非臆想的,相当于0
"abcd".substring(-1) //"abcd"
"abcd".substring(-1,5) //"abcd"
"abcd".substring(1,-5) // "a"
"abcd".substring(1,0) //"a"
"abcd".substring(-1,-5) // ""
"abcd".substring(0,0) // ""

(3)substr

语法: stringObject.substr(start,length)
start 必需。要抽取的子串的起始下标。必须是数值。如果是负数,那么该参数声明从字符串的尾部开始算起的位置。也就是说,-1 指字符串中最后一个字符,-2 指倒数第二个字符,以此类推。
length 可选。子串中的字符数。必须是数值。如果省略了该参数,那么返回从 stringObject 的开始位置到结尾的字串。为负数时返回空字符串

// 正数
"abcd".substr(0) //"abcd"
"abcd".substr() //"abcd"
"abcd".substr(1,5) //"bcd"
// 负数
"abcd".substr(-1) //"d"
"abcd".substr(-1,5) //"d"
"abcd".substr(-2,1) // "c"
"abcd".substr(-2,-1) // ""
"abcd".substr(2,-1) // ""

说明:
substr() 的参数指定的是子串的开始位置和长度,因此它可以替代 substring() 和 slice() 来使用。start可以是负数有意义。
重要事项:ECMAscript 没有对该方法进行标准化,因此反对使用它。
重要事项:在 IE 4 中,参数 start 的值无效。在这个 BUG 中,start 规定的是第 0 个字符的位置。在之后的版本中,此 BUG 已被修正。

总结(看完理解通透了):

1.slice第一个参数和第二个参数都是字符串的索引值,都可为负数,代表反向的;其返回的子字符串必须是从左到有的,即第二个参数的索引不可以在第一个索引的前面,否则为空
2.substring第一个参数和第二个参数都是字符串的索引值,但是负数特殊相当于0,不代表反向的索引;比slice而言第二个索引可以在第一个索引前面 3.substr ECMAscript标准化没有标准化,不建议用;第一个参数为字符串的索引值,可以为负数,代表反向的索引,第二个参数为截取字符串的长度,因此为负数时相当于0,返回空字符串

2. 场景二、替换

replace语法:stringObject.replace(regexp/substr,replacement)
regexp/substr
必需。规定子字符串或要替换的模式的 RegExp 对象。
请注意,如果该值是一个字符串,则将它作为要检索的直接量文本模式,而不是首先被转换为 RegExp 对象。
replacement 必需。一个字符串值。规定了替换文本或生成替换文本的函数。

// 将把 "Doe, John" 转换为 "John Doe" 的形式
let name = "Doe, John";
name.replace(/(\w+)\s*, \s*(\w+)/, "$2 $1");
// 将把所有的花引号替换为直引号:
name = '"a", "b"';
name.replace(/"([^"]*)"/g, "'$1'");
// 把字符串中所有单词的首字母都转换为大写:
name = 'aaa bbb ccc';
uw=name.replace(/\b\w+\b/g, function(word){
    
    
  return word.substring(0,1).toUpperCase()+word.substring(1);}
  );

案例:字符串转驼峰

var str="border-bottom-color";
function convertToCamelCase(str) {
    
    
 return str.replace(/-(\w)/g, function($0, $1) {
    
    
    return $1.toUpperCase();
  });
};
convertToCamelCase(str);

说明:
replacement 可以是字符串,也可以是函数。如果它是字符串,那么每个匹配都将由字符串替换。但是 replacement 中的 $ 字符具有特定的含义。如下表所示,它说明从模式匹配得到的字符串将用于替换。

字符 替换文本
$1、$2、…、$99 与 regexp 中的第 1 到第 99 个子表达式相匹配的文本。
$& 与 regexp 相匹配的子串。
$` 位于匹配子串左侧的文本。
$’ 位于匹配子串右侧的文本。
$$ 直接量符号。

3. 场景三、对象与字符串转换

var obj={
    
    "a":"dt","b":"yuiyi"}
var obj1={
    
    "a":"dt","b":{
    
    "a":"dt"}}
var str = JSON.stringify(obj) // '{"a":"dt","b":"yuiyi"}'
var str1 = JSON.stringify(obj1) //'{"a":"dt","b":{"a":"dt"}}'
JSON.parse(str) // {a: "dt", b: "yuiyi"}
JSON.parse(str1) //{a: "dt", b: {…}}

可用于对象的浅拷贝,以及对象的序列化传参,例如vue中的路由query传参。

4. 场景四、字符串正则

字符串支持4种用正则的方法

api 描述
match() 找到一个或多个正则表达式的匹配。
replace() 替换与正则表达式匹配的子串。
search() 检索与正则表达式相匹配的值。
split() 把字符串分割为字符串数组

具体用法可以参考w3chool

5. 场景五、转译

  1. 不要不必要地转义字符串中的字符,为什么?反斜杠会损害可读性,因此它们只应在必要时出现。
// bad
const foo = '\'this\' \i\s \"quoted\"';

// good
const foo = '\'this\' is "quoted"';
const foo = `my name is '${
      
      name}'`;
  1. 在正则表达式及,\n换行,\t制表等特殊字符用途,转义必须加
代码 结果
\b 退格键
\f 换页
\n 新行
\r 回车
\t 水平制表符
\v 垂直制表符
// 包含千分位的数字校验
let reg = /^\d{1,3}(,\d{3})*(\.\d{1,2})?$/
// 包含斜杆或者反斜杆校验
let reg1 = /\/|\\/
reg1.test("\\") // true

参考文献:
https://github.com/airbnb/javascript#strings
https://www.w3school.com.cn/js/js_strings.asp
http://c.biancheng.net/c/ascii/

猜你喜欢

转载自blog.csdn.net/qq_29510269/article/details/106409476