《JavaScript 高级程序设计》第五章 基本引用类型

317 阅读5分钟

基本引用类型

一、Date

date api基本上是参考java来的。

        console.log("startTime: "+ Date.now());  // 时间戳
​
        let currentDate = new Date();
        let currentTime = Date.now();
        console.log(currentDate.getTime()==currentTime); // true
​
        let date21 = new Date("May 23,2019");
        let date22 = new Date(Date.parse("May 23,2019"));
        console.log(date21.getTime()==date22.getTime());// true
​
        let date41 = new Date(Date.UTC(2000,1));
        let date42 = new Date(2000,1); // 跟本机时间有关 向后偏移8小时
        console.log(date41.getMonth());// 1 时间是2月份
        console.log(date42.getMonth());// 1 时间是2月份
        console.log(date41.getTime());// 949363200000
        console.log(date42.getTime());// 949334400000
​
        let date = new Date(2023,10,10,1,2,3);
        console.log(date.getMonth());// 10
        console.log(date.getSeconds()); // 3
        console.log(date.getMilliseconds());// 0
        console.log(date.getUTCMilliseconds());// 0
        
        console.log("endTime: "+ Date.now()); // 时间戳
​
        let date = new Date(2023,10,10,1,2,3);
        console.log(date.valueOf()); // 1699549323000
        console.log(date.toString());// Fri Nov 10 2023 01:02:03 GMT+0800 (中国标准时间)
        console.log(date.toLocaleString());// 2023/11/10 01:02:03
  

这里date.valueOf()返回的是毫秒时,所以操作符(> <)可以用来比较date的大小。

   let date = new Date();
   console.log(date.toUTCString());// 没有做时区偏移 Tue, 26 Sep 2023 00:35:57 GMT

二、RegExp

2.1 概述

类Perl的简洁语法来创建的,let expression = /pattern/flags;

pattern可以是字符串等,flags可以是多个标记。例如:let expression = /.at/gi; 表示所有以at结尾的三字符组合,忽略大小写。

g:global 查找全部字符串内容,而不是找到第一个就结束

i:不区分大小写

m:多行模式,查找到一行文本末尾会继续查找

y:粘附模式,表示只从lastIndex开始及以后的字符串

u:启动Unicode匹配

s:dotAll,表示元字符,匹配任何字符(包括\n或\r)

       let pattern1 = /[bc]a/i;
       let pattern2 = new RegExp("[bc]a","i");
       let text = "bcaeeebafffcaggg";
       let matches1 = pattern1.exec(text);
       let matches2 = pattern2.exec(text);
       console.log(matches1);  // ca 
       console.log(matches2); // ca
​
       let pattern3 = /[bc]a/gi;
       let matches3 = pattern3.exec(text);
       console.log(matches3[0]);  // ca 
       console.log(matches3.lastIndex);  // ca 
       console.log(matches3.index);  // ca 
       let matches4 = pattern3.exec(text);
       console.log(matches4.lastIndex);  // ba
       let matches5 = pattern3.exec(text);
       console.log(matches5[0]);  // ca

pattern加不加g是有区别的,含有g继续执行exec就是会在字符串中向前搜索下一个匹配项,不加g每次只会返回第一个匹配的信息。

2.2 RegExp的构造属性

这些属性是静态属性,会根据最后执行的正则表达式操作而变化。

        let pattern = /(.)hort/g;
        let text = "this has been a short summber";
        if (pattern.test(text)) {
            console.log(RegExp.input); // this has been a short summber
            console.log(RegExp.leftContext);// this has been a 
            console.log(RegExp.rightContext);//  summber
            console.log(RegExp.lastMatch);// short
            console.log(RegExp.lastParen);// s
        }
        let pattern2 = /(..)or(.)/g;
        let text2 = "this has been a short summber";
        if (pattern2.test(text2)) {
            console.log(RegExp.$1); // sh
            console.log(RegExp.$2);// t
        }

这里的(..)和(.)就表示两个捕获组。在生产环境中不要使用这些静态属性,因为没有任何Web标准出处。

三、原始值包装类型

Number(number的包装类型)、 Boolean(boolean包装类型) 、String(string的包装类型)

         let s1 = "some text";
         let s2 = new String(s1);
         console.log(typeof s1);// string
         console.log(typeof s2);// object
         console.log(s2 instanceof String);// true
         console.log(s1 instanceof string); // ReferenceError: string is not defined

按理说,s1只是一个原始值(字符串值),不应该有方法能调用,但是这里它能调用,其实是做了String转换的,在第二行执行完后,这个对象就置null,消失了。

         let a = 1000;
         console.log(a.toFixed(2)); // 1000.00
         console.log(a.toPrecision(1));// 1e+3
         console.log(a.toPrecision(4));// 1000
         console.log(a.toExponential(2));// 1.00e+3
         console.log(Number.isInteger(a));// true

toExponential 科学计数法表示。toFixed表示返回几位小数。

         let s = "a😊b";
         console.log(s.length); // 4
         console.log(s.charAt(0)); // a
         console.log(s.charAt(1)); // ?
         console.log(s.charAt(2));// ?
         console.log(s.charAt(3));// b
​
         console.log(s.charCodeAt(0)); // 97
         console.log(s.charCodeAt(1)); // 55357
         console.log(s.charCodeAt(2));// 56842
         console.log(s.charCodeAt(3));// 98
​
         console.log(s.codePointAt(0)); // 97
         console.log(s.codePointAt(1)); // 128522
         console.log(s.codePointAt(2));// 56842
         console.log(s.codePointAt(3));// 98
​
         console.log(String.fromCharCode(97,55357,56842,98)); // a😊b
         console.log(String.fromCodePoint(97,128522,98));// a😊b

charAt 和 charCodeAt 表示的字符有一定的范围,超出范围就不行了。

这里的表情符号😊使用两个码元(charCode),组成一个代理对,可以用一个码点codePoint表示。

有些字符可以用一个BMP字符表示,也可以用一个代理对表示。

String的api

        let s1 = "helloworld";
        console.log(s1.concat("xxx","yyy","zzz")); // helloworldxxxyyyzzz
        console.log(s1.slice(-3));// rld
        console.log(s1.slice(3,-4));//low
        console.log(s1.substr(-3));//rld
        console.log(s1.substr(3,-4));// ""空串
        console.log(s1.substring(-3));// helloworld
        console.log(s1.substring(3,-4));//hel
        console.log(s1.indexOf("o"));// 4
        console.log(s1.lastIndexOf("o"));// 6
        console.log(s1.startsWith("hel"));// true
        console.log(s1.includes("hel"));// true
        console.log(s1.endsWith("ld"));// true
        console.log(s1.trim());// helloworld
        console.log(s1.repeat(2)+"man");// helloworldhelloworldman
        console.log(s1.padStart(2, "."));// helloworld
        console.log(s1[Symbol.iterator]().next());// {value: 'h', done: false}
        console.log(s1[Symbol.iterator]().next());// {value: 'h', done: false}
        console.log(s1[Symbol.iterator]().next());// {value: 'h', done: false}
        console.log([...s1]);//['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
        console.log(s1.toUpperCase());// HELLOWORLD
        console.log(s1.toLowerCase());// helloworld

        let text = "cat,bat,sat";
        let pattern = /.at/;
        let matches = text.match(pattern);
        console.log(matches.index);// 0
        console.log(matches[0]);// cat
        console.log(matches[1]);// undefined
        console.log(pattern.lastIndex);// 0
        console.log(text.replace("at","ond"));// cond,bat,sat
        console.log(text.replace(/(.at)/g,"word($1)"));// word(cat),word(bat),word(sat)
        console.log(text.replace(/(.at)/g,"word($2)"));// word($2),word($2),word($2)
        console.log(text.replace(/(.at)/g,"word($3)"));// word($3),word($3),word($3)

        let s2 = "yellow";
        console.log(s2.localeCompare("brick"));// 1

ps: 正则中的捕获组112,来自openAi的解释:

在正则表达式中,括号 ( ) 用来创建捕获组(capturing group)。捕获组允许你在匹配中提取和操作子字符串。

在正则表达式中,你可以使用多个捕获组,每个捕获组用括号 ( ) 定义。当你使用多个捕获组时,可以通过 $1$2$3 等来引用这些捕获组中匹配到的内容。

let text = "apple123,banana456,orange789";
let regex = /([a-zA-Z]+)(\d+)/g;

let matches = text.match(regex);

for (let i = 0; i < matches.length; i++) {
    console.log(matches[i]);  // 输出每个匹配的字符串
    console.log(matches[i].replace(regex, "word($1)($2)"));  // 使用捕获组替换
}

在这个例子中,正则表达式 ([a-zA-Z]+)(\d+) 包含两个捕获组。第一个捕获组 ([a-zA-Z]+) 匹配一个或多个字母,第二个捕获组 (\d+) 匹配一个或多个数字。

matches[i].replace(regex, "word($1)($2)") 中,$1 表示第一个捕获组(匹配字母),$2 表示第二个捕获组(匹配数字)。替换操作会将匹配到的字符串中的字母和数字分别用括号括起来,形成类似 "word(apple)(123)"、"word(banana)(456)"、"word(orange)(789)" 的结果。

四、单例内置对象

4.1、Global

在全局作用域中定义的变量和函数都会变成global的对象的属性。window对象实现为Global对象的代理。

       let uri = "http://www.baidu.com/hha 90"
       console.log(encodeURI(uri));// http://www.baidu.com/hha%2090
       console.log(encodeURIComponent(uri));// http%3A%2F%2Fwww.baidu.com%2Fhha%2090
       console.log(decodeURI(encodeURI(uri)));// http://www.baidu.com/hha 90
       console.log(decodeURIComponent(encodeURIComponent(uri)));// http://www.baidu.com/hha 90

encodeURI不会编码属于URL组件的特殊字符,比如// : ?等,而encodeURIComponent编码所有遇到的非标准字符。

神奇的eval() 方法,就是一个完整的ECMAScript的解释器。

        eval("console.log('aaaa')"); // aaaa
        eval("function sayHi(){ console.log('bbb')};");
        sayHi(); // bbb
        eval("let msg = 'hello'"); 
        console.log(msg);// Uncaught ReferenceError: msg is not defined

这里因为eval中定义的函数和变量都不会被提升,所以msg会报错。

4.2、Math对象

       let values = [1,2,3];
       console.log(Math.max(...values));// 3
       console.log(Math.min(...values)); // 1
       console.log(Math.ceil(25.1));// 26
       console.log(Math.floor(25.9));// 25
       console.log(Math.round(25.9));// 26
       console.log(Math.fround(25.9));// 25.899999618530273
       console.log(Math.floor(Math.random() *10) + 1);  // 1
       console.log(Math.pow(2,3)); // 8

fround: 返回数值最接近的单精度浮点值表示。

random: 返回的是0~1之间的值,包含0但不包含1。