Boolean、Number、String特性
Boolean
Boolean是对应布尔值的引用类型。要创建一个 Boolean 对象,就使用 Boolean 构造函数并传入true 或 false。
let booleanObject = new Boolean(true);
创建之后,Boolean实例会重写valueOf()方法,返回true或false。 toString()方法返回字符串"true"
或"false"
。但是Boolean对象在ECMAScript中用得很少,不仅如此,它们还容易引起误会,尤其是在布尔表达式中使用 Boolean 对象时,例如:
let falseObject = new Boolean(false);
let result = falseObject && true;
console.log(result); // true
let falseValue = false;
result = falseValue && true;
console.log(result); // false
由于所有对象在布尔表达式中都会自动转换为true,因此 true && true 为 true;
Boolean 对象是 Boolean 类型的实例,在使用instaceof 操作符时返回 true,但对原始值则返回 false
console.log(typeof falseObject); // object
console.log(typeof falseValue); // boolean
console.log(falseObject instanceof Boolean); // true
console.log(falseValue instanceof Boolean); // false
Number
Number是对应数值的引用类型,要创建一个Number对象,就要使用Number构造函数并传入一个数值,如下:
let numberObject = new Number(10);
与Boolean 类型一样,Number 类型重写了 valueOf()
、toLocaleString()
和 toString()
方法。valueOf()方法返回 Number 对象表示的原始数值,另外两个方法返回数值字符串。toString()方法可选地接收一个表示基数的参数,并返回相应基数形式的数值字符串。
let num = 10;
console.log(num.toString()); // "10"
console.log(num.toString(2)); // "1010" 二进制
console.log(num.toString(8)); // "12" 八进制
console.log(num.toString(10)); // "10" 十进制
console.log(num.toString(16)); // "a" 十六进制
console.log(num.toFixed(2)); // "10.00"
let num1 = 10.005;
console.log(num1.toFixed(2)); // "10.01" 超出指定小数位,则四舍五入法
console.log(num.toExponential()) //"1e+1" 返回科学记数方式
toPrecision()
方法会根据情况返回最合理的输出结果,可能是固定长度,也可能是科学记数法形式。这个方法接收一个参数,表示结果中数字的总位数(不包含指数)。
let num = 99;
console.log(num.toPrecision(1)); // "1e+2" 因为99不能用一位数字表示,所以将其舍入为100,就可以用1位数字表示
console.log(num.toPrecision(2)); // "99"
console.log(num.toPrecision(3)); // "99.0"
本质上,toPrecision()方法会根据数值和精度来决定调用 toFixed()还是 toExponential()。为了以正确的小数位精确表示数值,这 3 个方法都会向上或向下舍入。
isInteger()
方法,用于辨别一个数值是否保存为整数。
console.log(Number.isInteger(1)); // true
console.log(Number.isInteger(1.00)); // true
console.log(Number.isInteger(1.01)); // false
String
String是对应字符串的引用类型。
let stringValue=new 'hello world";
字符串类型有多种方法:
concat()
该方法可以接收任意多个参数,但更常用的方式是使用“ + ”- ECMA提供了三个提取子字符串的方法:
slice()、substr() 、substring()
这三个方法都返回它们字符串的子字符串,且都接收一或两个参数。第一个参数是子字符串开始的下标位置,对于slice
和substring
而言,第二个参数是子字符串提取结束的位置(🙅♂️不包括该位置),对于substr
而言,第二个参数表示返回的子字符串字符数量。任何情况下,省略第二个参数都意味着提取到字符串末尾。
这三个方法容易混淆,下面一一举例:
!! slice、substring 与 substr 的区别:
以下注释的内容很重要。
let str = 'hello world';
// 只有一个参数默认截到最后
console.log(str.slice(1)); //ello world
console.log(str.substring(1)); //ello world
console.log(str.substr(1)); //ello world
// slice和substring:第一位参数是开始位置,第二位参数是结束位置
console.log(str.slice(1,3)); //el
console.log(str.substring(1,3)); //el
// 正参数时slice和substring的区别
// substring(),两个参数时会将较小的参数作为起点,较大的作为终点
console.log(str.slice(3,1)) // ''
console.log(str.substring(3,1)) //el
// substr第二个参数代表字符数量
console.log(str.substr(1,3)); //ell 从位置1开始,截三位字符
// 以下是有负参数的情况,三个规则都不一样了
// slice() 所有负值参数都当成字符串长度加上负参数值
console.log(str.slice(-3)) // 'rld' str的长度为11,11+(-3)=8,也就是从小标8开始截,到最后位置
console.log(str.slice(-3, 4)) // '' => slice(8, 4)
console.log(str.slice(-3, -1)) // 'rl' 11+(-3)=8; 11+(-1)=10, 相当于slice(8,10)
// substring 将所有负参数都转换为0
console.log(str.substring(-3)) // "hello world" 相当于substring(0)
console.log(str.substring(-3, 5)) // "hello" 相当于substring(0,5)
console.log(str.substring(-3, -2)) // '' 相当于substring(0,0)
// substr 把第一个负参数值加上字符串长度作为参数,第二个负参数转换为0
console.log(str.substr(-8)) // "lo world" -8+11=3 相当于substr(3)
console.log(str.substr(-3, 3)) // "rld" 相当于substr(8,3)
console.log(str.substr(-3, -3)) //'' 相当于substr(8,0)
- 字符串位置方法
indexOf()、lastIndexOf()
,用于定位子字符串,有一或两个参数
二者区别在于:indexOf()方法从字符串开头开始查找子字符串,lastIndexOf()方法从字符串末开始查找。第二个参数可选,表示开始搜索的位置。
let str = 'hello world';
// 只有一个参数的情况
console.log(str.indexOf('o')) // 4
console.log(str.lastIndexOf('o')) // 7
console.log(str.indexOf(' w')); // 5
console.log(str.indexOf('1')) // -1
console.log(str.lastIndexOf('1')) // -1
// 两个参数
console.log(str.indexOf('o', 6)) // 7 从下标6开始找
console.log(str.lastIndexOf('o', 6)) // 4 反过来数,也就是倒数第7个
案例1🌰:找出字符串中所有目标子字符串,以数组形式输出下标。
let stringValue = "Lorem ipsum dolor sit amet, consectetur adipisicing elit";
let arr = [];
let pos = stringValue.indexOf('e'); // 先找出第一个e的下标位置
while(pos > -1) {
arr.push(pos);
pos = stringValue.indexOf('e', pos + 1); // 每次循环匹配,在上一个位置后面匹配
}
console.log(arr); // [ 3, 24, 32, 35, 52 ]
- 字符串包含方法
startsWith()、endsWith()、includes()
,这些方法从字符串中🔍传入的字符串,且返回布尔值。
区别在于:startsWith()从索引为0开始检索;endsWith()从索引为string.length-substring.length
开始检索;而includes()从整个字符串检索。
let message = "foobarbaz";
console.log(message.startsWith("foo")); // true
console.log(message.startsWith("bar")); // false
console.log(message.endsWith("baz")); // true
console.log(message.endsWith("bar")); // false
console.log(message.includes("bar")); // true
console.log(message.includes("qux")); // false
startsWith()
和includes()
方法接收可选的第二个参数,表示开始搜索的位置。
let message = "foobarbaz";
console.log(message.startsWith("foo")); // true
console.log(message.startsWith("foo", 1)); // false
console.log(message.includes("bar")); // true
console.log(message.includes("bar", 4)); // false
endsWith()
方法接收可选的第二个参数,表示应该当作字符串末尾的位置。
console.log(message.endsWith("bar")); // false
console.log(message.endsWith("bar", 6)); // true message.length - "bar".length = 9-3 = 6,从下标6开始检索,所以为false
trim()
、trimLeft()
、trimRight()
方法,用于删除字符串前后空格符。不会改变原字符串
let stringValue = " hello world ";
let trimmedStringValue = stringValue.trim();
console.log(trimmedStringValue); // "hello world"
另外,trimLeft()和 trimRight()方法分别用于从字符串开始和末尾清理空格符。
repeat()
方法
这个方法接收☝️个整数参数,表示要将字符串复制多少次,然后返回拼接所有副本后的结果。
let stringValue = "na ";
console.log(stringValue.repeat(16) + "batman");
// na na na na na na na na na na na na na na na na batman
padStart()
和padEnd()
复制字符串,如果小于指定长度,则在相应一边填充字符,直至满足长度条件。这两个方法的第一个参数是长度,第二个参数是可选的填充字符串,默认为空格(U+0020)。
可选的第二个参数并不限于一个字符。如果提供了多个字符的字符串,则会将其拼接并截断以匹配指定长度。此外,如果长度小于或等于字符串长度,则会返回原始字符串。
let stringValue = "foo";
console.log(stringValue.padStart(6)); // " foo"
console.log(stringValue.padEnd(6)); // "foo "
console.log(stringValue.padStart(9, ".")); // "......foo"
console.log(stringValue.padEnd(9, ".")); // "foo......"
console.log(stringValue.padStart(8, "bar")); // "barbafoo"
console.log(stringValue.padEnd(8, "bar")); // "foobarba"
console.log(stringValue.padStart(2)); // "foo"
console.log(stringValue.padEnd(2)); // "foo"
- 字符串迭代与解构
字符串的原型上暴露了一个@@iterator
方法,表示可以迭代字符串的每个字符。
可以像下面这样手动使用迭代器:
let message = "abc";
let stringIterator = message[Symbol.iterator]();
console.log(stringIterator.next()); // {value: "a", done: false}
console.log(stringIterator.next()); // {value: "b", done: false}
console.log(stringIterator.next()); // {value: "c", done: false}
console.log(stringIterator.next()); // {value: undefined, done: true}
有这个迭代器之后,字符串就可以通过解构操作符来解构了。比如,可以更方便地把字符串分割为字符数组:
console.log([..."abcde"]); // ["a", "b", "c", "d", "e"]
- 大小写转换
toLowerCase()、toLocaleLowerCase()、toUpperCase()、toLocaleUpperCase()
但在少数语言中(如土耳其语),Unicode 大小写转换需应用特殊规则,要使用地区特定的方法才能实现正确转换。通常,如果不知道代码涉及什么语言,则最好使用地区特定的转换方法。
let stringValue = "hello world";
console.log(stringValue.toLocaleUpperCase()); // "HELLO WORLD"
console.log(stringValue.toUpperCase()); // "HELLO WORLD"
console.log(stringValue.toLocaleLowerCase()); // "hello world"
console.log(stringValue.toLowerCase()); // "hello world"
- 字符串模式匹配方法
match()、search()、replace()、split()
match()方法
本质上跟RegExp对象的exec()方法相同,match()方法接收一个参数,可以是正则表达式字符串也可以是RegExp对象。
let text = "cat, bat, sat, fat";
let pattern = /.at/;
let matches = text.match(pattern); // 等价于 pattern.exec(text)
console.log(matches.index); // 0
console.log(matches[0]); // "cat"
console.log(pattern.lastIndex); // 0
search()方法
参数与match一样,正则表达式字符串或 RegExp 对象。返回模式第一个匹配的位置索引,如果没有找到返回-1。
let text = "cat, bat, sat, fat";
console.log(text.search(/bat/)); // 5
console.log(text.search(/bata/)); // -1
replace()方法
接收两个参数 (RegExp对象或一个字符串不会转为正则,一个字符串或函数),如果第一个参数是字符串,那么只会替换第一个子字符串。要想替换所有子字符串,第一个参数必须为正则表达式并且带全局标记。
// 参数是字符串
let text = "cat, bat, sat, fat";
let result = text.replace("at", "ond");
console.log(result); // "cond, bat, sat, fat" 只会替换第一个子字符串
result = text.replace(/at/g, "ond");
console.log(result); // "cond, bond, sond, fond"
// 参数是函数
function htmlEscape(text) {
return text.replace(/[<>"&]/g, function(match, pos, originalText) {
switch(match) {
case "<":
return "<";
case ">":
return ">";
case "&":
return "&";
case "\"":
return """;
}
});
}
console.log(htmlEscape("<p class=\"greeting\">Hello world!</p>"));
// "<p class="greeting">Hello world!</p>"
split()方法
根据传入的分隔符将字符串拆分成数组,参数可以使字符串,也可以是RegExp对象,第二个参数可选,表示数组大小。
let colorText = "red,blue,green,yellow";
colorText.split(","); // ["red", "blue", "green", "yellow"]
colorText.split(",", 2); // ["red", "blue"]
colorText.split( dhi/[^,]+/); // ["", ",", ",", ",", ""]
- localeCompare()方法
用于比较两个字符串,返回正值、负值和0。
如果按照字母表顺序,字符串应该排在字符串参数后头,则返回正值(通常为1)。反之返回负值(通常为-1)。如果字符串和字符串参数相等,返回0。
let stringValue = "yellow";
console.log(stringValue.localeCompare("brick")); // 1
console.log(stringValue.localeCompare("yellow")); // 0
console.log(stringValue.localeCompare("zoo")); // -1