JavaScript学习-05-基本引用类型

111 阅读5分钟

JavaScript学习-05-基本引用类型

引用类型可以称为对象定义,描述了自己的对应应有的属性和方法(类)

对象被认为是某个特定引用类型的实例

函数也是一种引用类型

5.1 Date

  • Date类型将日期保存为1970年1月1日零时至今所经过的毫秒数

  • 在不给Date构造函数传参数的情况下,创建的对象将保存当前日期和时间

    let now = new Date();
    
  • Date.parse()方法接收一个表示日期的字符串参数,尝试将这个字符串转换为表示该日期的毫秒数;

    如果传给Date.parse()的字符串并不表示日期,则该方法返回NaN

    let someDate = new Date(Date.parse('May 23, 2019'));
    
  • 如果直接把表示日期的字符串传给Date构造函数,那么Date会在后台调用Date.parse()

    let someDate = new Date('May 23, 2019'); // 和上面的是等价的
    
  • Date.UTC()方法也返回日期的毫秒表示,但是传入的参数不同:传给Date.UTC()的参数是年、零起点月数(1月是0,2月是1,以此类推)、日(131)、时(023)、分、秒和毫秒

    这些参数,只有年和月是必须的,如果不提供日,那么默认为1,其余的参数默认值是0

    let y2k = new Date(Date.UTC(2000, 0));
    let allFives = new Date(Date.UTC(2005, 4, 5, 17, 55, 55)); // 月数用4表示5
    
  • Date.UTC()方法和Date.parse()方法一样,也会被Date构造函数隐式调用

  • Date.now()方法,返回表示方法执行日期和时间的毫秒数

    let start = Date.now();
    doSomething();
    let stop = Date.now();
    result = stop - start; // 计算代码的执行时间
    

5.1.1 继承的方法

Date类型重写了Object的toLocaleString()toString()valueOf()方法。

  • toLocaleString()方法返回与浏览器的本地环境一致的日期和时间,通常包含针对时间的AM(上午)或PM(下午),但是不包含时区信息

  • toString()方法通常返回带时区信息的日期和时间,而时间也是以24小时表示的

    // 2019年2月1日零点
    toLocaleString() - 2/1/2019 12:00:00 AM
    toString() - Thu Feb 1 2019 00:00:00 GMT-0800 (Pacific Standard Time)
    
  • valueOf()方法返回的是日期的毫秒表示,因为,可以直接比较两个日期的大小,实际上会调用valueOf()方法,然后比较毫秒值的大小

    let date1 = new Date(2019, 0, 1);
    let date2 = new Date(2019, 1, 1);
    
    console.log(date1 < date2); // true
    

5.1.2 日期格式化方法

日期的格式化方法的返回值,会因浏览器而异,因此一般不会使用,通常会自己封装函数来格式化日期

5.1.3 日期/时间组件方法

用的时候再去查

5.2 RegExp

let expression = /pattern/flags;
  • pattern: 模式,包括字符类、限定符、分组、向前查找和反向引用

  • flag: 标记, 每个正则表达式可以带0个或多个flags,用于控制正则表达式的行为

    • g: 全局模式,表示查找字符串的全部内容,而不是找到第一个匹配的内容就结束
    • i: 不区分带小写,忽略大小写
    • m: 多行模式,表示查找到一行文本末尾时会继续查找
    • y: 粘附模式,表示只查找从lastIndex开始及之后的字符串
    • u: 启用Unicode匹配
    • s: dotAll模式,表示元字符.匹配任何字符(包括\n或\r)
    let pattern1 = /at/g; // 匹配字符串中所有的'at'
    let pattern2 = /[bc]at/i; // 匹配第一个'bat'或'cat',忽略大小写
    let pattern3 = /.at/gi; // 匹配所有以at结尾的三字符数组,忽略大小写
    
  • 元字符在模式中必须转义:元字符在正则表达式中都有一种或多种特殊功能,如果要匹配这些字符本身,就必须使用反斜杠来转义

    ( ) [ ] { } \ ^ $ | ? * + .
    
    let pattern1 = /[bc]at/i; // 匹配第一个'bat'或'cat',忽略大小写
    let pattern2 = /\[bc\]at/i; // 匹配第一个'[bc]at',忽略大小写
    let pattern3 = /.at/gi; // 匹配所有以'at'结尾的三字符组合,忽略大小写
    let pattern4 = /\.at/gi; // 匹配所有'.at',忽略大小写
    
  • 也可以使用RegExp构造函数来创建,接收两个参数:模式字符串和标记字符串

    let pattern1 = /[bc]at/i; // 匹配第一个'bat'或'cat',忽略大小写
    let pattern2 = new RegExp('[bc]at', 'i'); // 效果同pattern1,注意这里的参数都是字符串,如果字符串里包含了元字符,则需要二次转义 '\\[bc\\]at'
    
  • 也可以基于已有的正则表达式实例,并可选择性的修改它们的标记

    let re1 = /cat/g;
    console.log(re1); // '/cat/g'
    
    let re2 = new RegExp(re1, 'i');
    console.log(re2); // '/cat/i'
    

5.2.1 RegExp实例属性

每个RegExp实例都有下列属性

属性类型信息
global布尔值表示是否设置了g标记
ignoreCase布尔值表示是否设置了i标记
unicode布尔值表示是否设置了u标记
sticky布尔值表示是否设置了y标记
lastIndex整数表示在源字符串中下一次搜索的开始位置,始终从0开始
multiline布尔值表示是否设置了m标记
dotAll布尔值表示是否设置了s标记
source字符串正则表达式的字面量字符串(不是传给构造函数的模式字符串),没有开头和结尾的斜杠
flags字符串正则表达式的标记字符串

5.2.2 RegExp实例方法

  • exec()

    • 方法只接收一个参数,即要应用模式的字符串。如果找到了匹配项,则返回包含第一个匹配信息的数组;如果没有找到匹配项,则返回null

    • 返回的数组虽然是Array的实例,但包含两个额外的属性:indexinput,index是字符串中匹配模式的起始位置,input是要查找的字符串

    • 数组中第一个元素是匹配整个模式的字符串,其他元素是与表达式中捕获组匹配的字符串

      let text = 'mom and dad and baby';
      let pattern = /mom( and dad( and baby)?)?/gi;
      
      let matches = pattern.exec(text);
      console.log(matches.index); // 0
      console.log(matches.input); // 'mom and dad and baby'
      console.log(matches[0]); // 'mom and dad and baby'
      console.log(matches[1]); // ' and dad and baby'
      console.log(matches[2]); // ' and baby'
      
    • 如果模式设置了全局标记,则每次调用exec()方法会返回一个匹配的信息,如果没有设置全局标记,则无论对同一个字符串用多少次exec(),也只会返回第一个匹配的信息

      let text = 'cat, bat, sat, fat';
      let pattern = /.at/;
      
      let matches = pattern.exec(text);
      console.log(matches.index); // 0
      console.log(matches[0]); // cat
      console.log(pattern.lastIndex); // 0
      
      matches = pattern.exec(text);
      console.log(matches.index); // 0
      console.log(matches[0]); // cat
      console.log(pattern.lastIndex); // 0
      
      let text = 'cat, bat, sat, fat';
      let pattern = /.at/g;
      let matches = pattern.exec(text); 
      console.log(mathces.index); // 0
      console.log(matches[0]); // cat
      console.log(pattern.lastIndex); // 3
      
      matches = pattern.exec(text);
      console.log(matches.index); // 5
      console.log(matches[0]); // bat
      console.log(pattern.lastIndex); // 8
      
      matches = pattern.exec(text);
      console.log(matches.index); // 10
      console.log(matches[1]); // sat
      console.log(pattern.lastIndex); // 13
      
  • test()

    • test()方法接收一个字符串参数,如果输入的文本与模式匹配,则参数返回true,否则返回false

      let text = '000-00-0000';
      let pattern = /\d{3}-\d{2}-\d{4}/;
      
      console.log(pattern.test(text)); // true
      
    • toLocaleString()toString()返回的都是正则表达式的字面量的形式

5.2.3 RegExp构造函数属性

  • RegExp构造函数也有几个属性(在其他语言中,这种属性被称为静态属性,比如Java中的静态属性)

  • 这些属性适用于作用域中的所有正则表达式,而且会根据最后执行的正则表达式操作而变化

  • 每个属性都有一个全名和简写

    全名简写说明
    input$_最后搜索的字符串
    lastMatch$&最后匹配的文本
    lastParen$+最后匹配的捕获组
    leftContext$`input字符串中出现在lastMatch前面的文本
    rightContext$'input字符串出现在lastMatch后面的文本
    let text = 'this has been a short summer';
    let pattern = /(.)hort/g;
    
    if (pattern.test(text)) {
      console.log(RegExp.input); // 'this has been a short summer'
      console.log(RegExp.leftContext); // 'this has been a'
      console.log(RegExp.rightContext); // 'summer'
      console.log(RegExp.lastMatch); // 'short'
      console.log(RegExp.lastParen); // 's'
    }
    
    或者
    if (pattern.test(text)) {
      console.log(RegExp.$_); // 'this has been a short summer'
      console.log(RegExp['$`']); // 'this has been a'
      console.log(RegExp['$']); // 'summer'
      console.log(RegExp['$&']); // 'short'
      console.log(RegExp['$+']); // 's'
    }
    
  • RegExp还有其他几个构造函数属性,可以存储最多9个捕获组的匹配项,这些属性通过RegExp.1 RegExp.1~RegExp.2访问,分别包含了第1~9个捕获组的匹配项

    let text = 'this has bben a short summer';
    let pattern = /(..)or(.)/g;
    
    if (pattern.test(text)) {
      console.log(RegExp.$1); // sh
      console.log(RegExp.$2); // t
    }
    

5.2.4 模式局限

5.3 原始值包装类型

每当用到某个原始值的方法或属性时,后台都会创建一个相应原始包装类型的对象,从而暴露出操作原始值的各种方法

let s1 = 'some text';
let s2 = s1.substring(2);

// 1. 创建一个String类型的实例
// 2. 调用实例上的特定方法
// 3. 销毁实例
let s1 = new String('some text');
let s2 = s1.substring(2);
s1 = null;

5.3.1 Boolean

很少使用,容易引起误解,建议永远不要使用

let falseObject = new Boolean(false); // true

5.3.2 Number

  • 进制转换
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'
  • 截取小数位数
let num = 10;
console.log(num.toFixed(2)); // '10.00'

如果数值本身的小数位数超过了参数指定的位数,则四舍五入到最近的小数位

let num = 10.005;
console.log(num.toFixed(2)); // '10.01'
  • 科学计数法
let num = 10;
console.log(num.toExponential(1)); // 参数表示结果中小数的位数:'1.0e+1'
  • 如果想得到数值的最适当的形式,可以使用toPrecision(),方法接收一个参数,表示结果中数字的总位数
let num = 99;
console.log(num.toPrecision(1)); // '1e+2'
console.log(num.toPrecision(2)); // '99'
console.log(num.toPrecision(3)); // '99.0'
  • 判断一个数值是否是整数:Number.isInteger()
console.log(Number.isInteger(1)); // true
console.log(Number.isInteger(1.00)); // true
console.log(Number.isInteger(1.01)); // false

5.3.3 String

5.3.3.1 JavaScript字符

  • 给定索引位置的字符: charAt()

    let message = 'abcde';
    console.log(message.charAt(2)); // 'c'
    
  • 查看指定字符的字符编码:charCodeAt(),参数为索引,返回指定索引位置的码元值

    let message = 'abcde';
    console.log(message.charCodeAt(2)); // 99
    
  • 根据码元值创建字符串: fromCharCode()

    console.log(String.fromCharCode(97, 98, 99, 100, 101)); // 'abcde'
    

5.3.3.2 normalize()方法

5.3.3.3 字符串操作方法

  • concat()方法,+号更经常用

    let stringValue = 'hello ';
    let result = stringValue.concat('world'); // 'hello world'
    
    // 也可以拼接多个字符串
    let result = stringValue.concat('world', '!'); // 'hello world!'
    
  • 提取字符串

    • slice(),接收2个参数:字符串开始的位置和字符串结束(不包括)的位置,左闭右开

    • substring(),接收2个参数:字符串开始的位置和字符串结束(不包括)的位置,左闭右开

    • substr(),接收2个参数:字符串开始的位置和返回的子字符串的数量

    • 任何情况下,省略第二个参数意味着提取到字符串末尾

      let stringValue = 'hello world';
      console.log(stringValue.slice(3, 7)); // 'lo w'
      console.log(stringValue.substring(3, 7)); // 'lo w'
      console.log(stringValue.substr(3, 7)); // 'lo worl'
      
    • 当某个参数是负值时,slice方法将所有负值参数都当成字符串长度加上负参数值

    • 当某个参数是负值时,substr方法将第一个负参数值当成字符串长度加上该值,第二个参数转换为0

    • 当某个参数是负值时,substring方法会将所有负参数值都转换为0

      let stringValue = 'hello world';
      console.log(stringValue.slice(-3)); // 'rld'
      console.log(stringValue.substring(-3)); // 'hello world'
      console.log(stringValue.substr(-3)); // 'rld'
      console.log(stringValue.slice(3, -4)); // 'lo w'
      console.log(stringValue.substring(3, -4)); // 'hel'
      console.log(stringValue.substr(3, -4)); // ''
      

5.3.3.4 字符串位置方法

  • 从头开始查找字符串indexOf(),从尾开始查找字符串lastIndexOf()

    let str = 'hello world';
    console.log(str.indexof('o')); // 4
    console.log(str.lastIndexOf('0')); // 7
    
  • 两个方法都接收第二个参数:表示开始搜索的位置,lastIndexOf会从这个参数指定的位置开始想字符串开头搜索

    let str = 'hello world';
    console.log(str.indexOf('o', 6)); // 7
    console.log(str.indexOf('o', 6)); // 4
    

5.3.3.5 字符串包含方法

  • startWith() endsWith() includes()

    let message = 'foobarbaz';
    
    console.log(message.startsWith('foo')); // true
    console.log(message.endsWith('bar')); // false
    console.log(message.endsWith('baz')); // true
    console.log(message.includes('bar')); // true
    
  • 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()方法接收可选的第二个参数,表示应该当做字符串末尾的位置,如果不提供,那么默认就是字符串长度

    let message = 'foobarbaz';
    
    console.log(message.startsWith('bar')); // false
    console.log(message.endsWith('bar', 6)); // true
    

5.3.3.6 trim()方法

  • trim()删除前后空格
  • trimLeft()删除前面的空格
  • trimRight()删除后面的空格

5.3.3.7 repeat()方法

  • 该方法接收一个整数参数,表示要将字符串复制多少次

5.3.3.8 padStart()padEnd()方法

padStart()padEnd()方法会复制字符串,如果小于指定长度,则在相应一边填充字符,直至满足长度条件

let str = 'foo';

console.log(str.padStart(6)); // '   foo'
console.log(str.padStart(9, '.')); // '......foo'

console.log(str.padEnd(6)); // 'foo   '
console.log(str.padEnd(9, '.')); // 'foo......'

可选的第二个参数可以是多个字符,如果是多个字符,则会将其拼接并截断以匹配指定长度

let str = 'foo';

console.log(str.padStart(8, 'bar')); // 'barbafoo'
console.log(str.padStart(2)); // 'foo'

console.log(str.padEnd(8, 'bar')); // 'foobarba'
console.log(str.padEnd(2)); // 'foo'

5.3.3.9 字符串迭代与解构

字符串的原型上暴露了一个@@iterator方法,表示可以迭代字符串的每个字符

let message = 'abc';
let strIterator = message[Symbol.iterator]();

console.log(strIterator.next()); // { value: 'a', done: false }
console.log(strIterator.next()); // { value: 'b', done: false }
console.log(strIterator.next()); // { value: 'c', done: false }
console.log(strIterator.next()); // { value: undefined, done: true }
for (const c of 'abcde') {
  console.log(c); // a b c d e
}
let message = 'abcde';
console.log([...message]); // ['a', 'b', 'c', 'd', 'e']

5.3.3.10 字符串大小写转换

  • toLowerCase()
  • toLocaleLowerCase()
  • toUpperCase()
  • toLocaleUpperCase()

5.3.3.11 字符串模式匹配方法

  • match(),本质上跟RegExp对象的exec()方法,方法接收一个参数,可以是一个正则表达式字符串,也可以是一个RegExp对象

    let text = 'cat, bat, sat, fat';
    let pattern = /.at/;
    
    let matches = text.match(pattern);
    console.log(macthes.index); // 0
    console.log(matches[0]); // 'cat'
    console.log(matches.lastIndex); // 0
    
  • search(),入参:正则表达式对象或RegExp对象,方法返回模式第一个匹配的位置索引,如果没有找到返回-1

    let text = 'cat, bat, sat, fat';
    let pos = text.search(/at/);
    console.log(pos); // 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'
    

    第二个参数是字符串的情况下,有几个特殊的字符序列,可以用来插入正则表达式操作的值

    字符序列替换文本
    $$$
    $&匹配整个模式的子字符串
    $'匹配的子字符串之前的字符串
    $`匹配的子字符串之后的字符串
    $n匹配第n个捕获组的字符串
    $nn匹配第nn个捕获组的字符串
    let text = 'cat, bat, sat, fat';
    result = text.replace(/(.at)/g, 'word ($1)');
    console.log(result); // word (cat), word (bat), word (sat), word (fat)
    
  • split(),入参:分隔符,可以是字符串,也可以是正则对象;还可以传入第二个参数,即数组大小,确保返回的数组不会超过指定大小

5.3.3.12 localeCompare()方法

比较两个字符串:

  • 参数排前面:1
  • 参数排后面:-1
  • 相等:0

5.4 单例内置对象

5.4.1 Global

兜底对象,针对的是不属于任何对象的属性和方法

5.4.1.1 URL编码方法

  • encodeURI()
  • encodeURIComponent()
  • decodeURI()
  • decodeURIComponent()

5.4.1.2 eval(),不建议使用

执行JS语句,ECMAScript解释器,接收一个参数:JS语句字符串

5.4.1.3 Global对象属性

属性说明
undefined特殊值undefined
NaN特殊值NaN
Infinity特殊值Infinity
ObjectObject的构造函数
ArrayArray的构造函数
FunctionFunction的构造函数
BooleanBoolean的构造函数
StringString的构造函数
NumberNumber的构造函数
DateDate的构造函数
RegExpRegExp的构造函数
SymbolSymbol的伪构造函数
ErrorError构造函数
......

5.4.1.4 window对象

虽然没有直接访问Global对象的方式,但浏览器将window对象实现为Global对象的代理,因此,所有全局作用域中声明的变量和函数都变成了window的属性

var color = 'red';

function sayColor() {
  console.log(window.color);
}

window.sayColor(); // 'red'

5.4.2 Math

5.4.2.1 Math对象属性

属性说明
Math.EE
Math.LN1010为底的自然对数
Math.LN22为底的自然对数
Math.PIPI的值

5.4.2.2 最大值和最小值

let max = Math.max(3, 54, 32, 16); 
console.log(max); // 54

let min = Math.min(3, 54, 32, 16);
console.log(min); // 3
let values = [1, 2, 3, 4, 5, 6];
let max = Math.max(...values); // 6

5.4.2.3 舍入

  • Math.ceil() 向上取整
  • Math.floor()向下取整
  • Math.round()四舍五入
  • Math.fround()返回数值最接近的单精度(32位)浮点值表示

5.4.2.4 随机数

  • Math.random() 0~1范围内的随机数

5.4.2.5 其他方法

  • Math.abs()绝对值
  • Math.exp() Math.E的x次幂

5.5 小结