石嘴山市网站建设_网站建设公司_表单提交_seo优化
2025/12/18 15:43:30 网站建设 项目流程

注意:本篇学习笔记基于原网站: JavaScript教程 - 廖雪峰的官方网站
笔记仅作学习留档使用

本篇目录

包装对象
Date
RegExp
补充1:正则表达式常用模式
补充2:正则表达式常见场景
补充3:转义规则总结与验证模式
JSON

typeof可以获取对象的类型,它返回对应名称的字符串

typeof 123; // 'number'
typeof 123n; // 'bigint'
typeof NaN; // 'number'
typeof 'str'; // 'string'
typeof true; // 'boolean'
typeof undefined; // 'undefined'
typeof Math.abs; // 'function'
typeof null; // 'object'
typeof []; // 'object'
typeof {}; // 'object'
  • numberbigintstringbooleanfunctionundefined有别于其他类型。
  • null的类型是objectArray的类型也是object
  • typeof将无法区分出nullArray和通常意义上的object——{}

包装对象

大概意思就是可以把别的类型的数据包装成object这个类型,numberbooleanstring都有包装对象,包装对象用new创建。因为类型不一样所以和原始值用===比较会返回false,意思是最好别用。

let n = new Number(123); // 'object'
let b = new Boolean(true); // 'object'
let s = new String('str'); // 'object'// === 比较
new Number(123) === 123; // false
new Boolean(true) === true; // false
new String('str') === 'str'; // false

想转换/查找类型可以用的:

  • 转换任意类型到numberparseInt()parseFloat()
  • 转换任意类型到string:用String(),或者直接调用某个对象的toString()方法(nullundefined没有这个方法)
  • 通常不必把任意类型转换为boolean再判断,因为可以直接写if (myVar) {...}
  • 判断ArrayArray.isArray(arr)
  • 判断nullmyVar === null
  • 判断某个全局变量是否存在:typeof window.myVar === 'undefined'
  • 函数内部,判断某个变量是否存在:typeof myVar === 'undefined'

关于调用toString(),如果是数字类型有点特殊情况:

123.toString(); // SyntaxError
123..toString(); // '123', 注意是两个点!
(123).toString(); // '123'

因为JavaScript采用IEEE 754规范双精度数字,只有一种数字类型,也就是说并没有为整数给出一种特定的类型,所有数字都是小数 。所以 123.0toString()行不通, 而123..toString(), 123 .toString()和(123).toString()都能得到正确的返回值

Date

日期类型,当前时间是浏览器从本机操作系统获取的时间

let now = new Date();// 不带 new:返回日期字符串
const dateString = Date();
console.log(typeof dateString); // 'string'
console.log(dateString instanceof Date); // falsnow; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
now.getFullYear(); // 2015, 年份
now.getMonth(); // 5, 月份,注意月份范围是0~11,5表示六月
now.getDate(); // 24, 表示24号
now.getDay(); // 3, 表示星期三
now.getHours(); // 19, 24小时制
now.getMinutes(); // 49, 分钟
now.getSeconds(); // 22, 秒
now.getMilliseconds(); // 875, 毫秒数
now.getTime(); // 1435146562875, 以number形式表示的时间戳

一些定义方式,注意很莫名其妙的小细节:JavaScript的月份范围用整数表示是0~11,0表示一月,1表示二月……,所以表示6月我们传入5

//也可以这样直接定义
const dateFromTimestamp = new Date(1700000000000);
console.log(date.toUTCString());        
// 输出:Tue, 14 Nov 2023 22:13:20 GMT
console.log(date.toLocaleString('zh-CN'));
// 输出:2023/11/15 06:13:20(北京时间)//创建指定日期和时间的对象
let d1 = new Date(2015, 5, 19, 20, 15, 30, 123);
console.log(d); // Fri Jun 19 2015 20:15:30 GMT+0800 (CST)//或者这样:符合ISO 8601格式的字符串
let d2 = Date.parse('2015-06-24T19:49:22.875+08:00');
console.log(d2); // 时间戳:1435146562875
let d2 = new Date(1435146562875);
console.log(d2);  // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
/*但有一点要注意,传入的字符串使用实际月份01~12,
但getMonth取出来会给你扣一变成五月*/
d.getMonth(); // 5 

RegExp(末尾有使用相关补充)

正则表达式

用正则表达式匹配字符串,方便并且可以复用代码

因为正则表达式也是用字符串表示的,且如果直接给出字符,就是精确匹配,所以首先是了解如何用字符来描述字符:

  • \d:匹配一个数字
  • \w:匹配一个字母或数字
  • .:可以匹配任意字符(对就是一个点)(除换行符)
'00\d'   // '007'√    '00A'×
'\d\d\d' // '020'√    '02B'×
'\w\w'   // 'js'√   '68'√   'p7'√ 
'js.'    // 'jsp'√  'jss'√  'js!'√ ....

对于会有长度变化的字符:

  • *:表示任意个字符(包括0个),
  • ?:表示0-1个字符,
  • +:表示≥1个字符,
  • {n}:表示n个字符,
  • {n,m}:表示n-m个字符
  • \s:匹配一个空格(也包括Tab等空白符)
// 用这个分析一下
'\d{2}\s+\d{3,8}''\d{2}' // 2个数字,例如'86'
'\s+'// ≥1个空白符,例如' '
'\d{3,12}' // 3-8个数字,例如'13922223333'↓
'\d{3}\s+\d{3,8}' --> '86 13922223333'
// 所以这个可以表示一串中国电话号,不过是我编的

在上面的情况中,若想要表达像86 139-2222-3333 这样,由于'-' 是特殊字符,所以正则表达式要改为'\d{2}\s+\d{3}\-\d{4}\-\d{4}' 。但如果是短横线前后有空格的格式,现在的方法就又不能匹配了。

所以介绍一些更精确的方式,用[]表示范围:

  • ^表示行的开头,^\d表示必须以数字开头。
  • $表示行的结束,\d$表示必须以数字结束。
  • A|B可以匹配A或B(单个字符或字符串都行)
[0-9a-zA-Z\_]   // 匹配一个数字、字母或者下划线;
[0-9a-zA-Z\_]+  //匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100','0_Z','js2015'等等;//JavaScript允许的变量名正则
/*由 字母或下划线 开头,
后接 任意个
由 数字、字母或者下划线
组成的字符串
*/
[a-zA-Z\_\$][0-9a-zA-Z\_\$]*
[a-zA-Z\_\$][0-9a-zA-Z\_\$]{0, 19} // 限制后接字符串为0-19个字符(J|j)ava(S|s)cript // 匹配j和s不同大小写的四种形式js     // 也可以匹配'jsp'
^js$  //变成了整行匹配,就只能匹配'js'

RegExp方式

创建一个正则表达式:

let re1 = /ABC\-001/;   // /正则表达式/
let re2 = new RegExp('ABC\\-001');  //new RegExp('正则表达式')re1; // /ABC\-001/
re2; // /ABC\-001///因为字符串的转义问题,new RegExp创建字符串的两个\\实际上是一个\// 判断正则表达式是否匹配
let re = /^\d{3}\-\d{3,8}$/;
re.test('010-12345'); // true
re.test('010-1234x'); // false
re.test('010 12345'); // false

切分字符串

用正则表达式切分,可以用来把不规范的输入转化成正确的数组

'a b   c'.split(' '); // ['a', 'b', '', '', 'c']
'a b   c'.split(/\s+/); // ['a', 'b', 'c']// [\s,]表示匹配“一个空白字符”或“一个逗号”
'a,b, c  d'.split(/[\s\,]+/); // ['a', 'b', 'c', 'd']
'a,b;; c  d'.split(/[\s\,\;]+/); // ['a', 'b', 'c', 'd']

分组

可以用正则表达式提取子串,用()表示要提取的分组,在RegExp对象上用exec()方法提取出子串。exec()方法在匹配成功后,返回一个Array,第一个元素是正则表达式匹配到的整个字符串,后面的字符串表示匹配成功的子串;匹配失败时返回null

let re = /^(\d{3})-(\d{3,8})$/;
// 定义了两个组,可以直接从匹配的字符串中提取出区号和本地号码
//提取
re.exec('010-12345'); // ['010-12345', '010', '12345']
re.exec('010 12345'); // null

贪婪匹配

正则匹配默认是贪婪匹配,这样会导致一些匹配不到:

let re = /^(\d+)(0*)$/;// 为了匹配出数字后面的0
re.exec('102300'); // ['102300', '102300', '']
// \d+贪婪匹配,直接把后面的0全部匹配了

使用非贪婪匹配需要在量词后面加上一个问号:

let re = /^(\d+?)(0*)$/;
re.exec('102300'); // ['102300', '1023', '00']

全局搜索

g表示全局匹配,全局匹配可以多次执行exec()方法来搜索一个匹配的字符串,每次运行后正则表达式本身会更新lastIndex属性,表示上次匹配到的最后索引。全局匹配类似搜索,因此不能使用/^...$/,那样只会最多匹配一次。

let r1 = /test/g;
// 等价于:
let r2 = new RegExp('test', 'g');let s = 'JavaScript, VBScript, JScript and ECMAScript';
let re=/[a-zA-Z]+Script/g;// 使用全局匹配:
re.exec(s); // ['JavaScript']
re.lastIndex; // 10re.exec(s); // ['VBScript']
re.lastIndex; // 20re.exec(s); // ['JScript']
re.lastIndex; // 29re.exec(s); // ['ECMAScript']
re.lastIndex; // 44re.exec(s); // null,直到结束仍没有匹配到

正则表达式还可以指定:

  • i标志,表示忽略大小写
  • m标志,表示执行多行匹配。

补充1:正则表达式常用模式

基础匹配

  • \D匹配非数字
  • \w匹配单词字符(字母、数字、下划线)
  • \W匹配非单词字符(\w之外的所有字符[^a-zA-Z0-9_]
  • \S匹配非空白字符
  • [^abc]匹配除 a、b、c 外的字符

位置锚点

  • \b匹配单词边界(一边是 \w,另一边是 \W或字符串边界)
  • \B匹配非单词边界(两边都是 \w或两边都是 \W
let str = "Hello, world! 你好 123 test_123";/*\b的场合*/
// 1. 查找所有单词边界位置
console.log(str.replace(/\b/g, '|'));
// 输出: "|Hello|, |world|! 你好 |123| |test_123|"
// 注意:中文不被视为单词字符,所以"你好"前后没有边界// 2. 匹配整个单词
console.log(str.match(/\b\w+\b/g));
// 输出: ['Hello', 'world', '123', 'test_123']// 3. 查找以特定字母开头的单词
console.log(str.match(/\bw\w*\b/g));  // 以w开头的单词
// 输出: ['world']// 4. 查找以特定字母结尾的单词
console.log(str.match(/\b\w+d\b/g));  // 以d结尾的单词
// 输出: ['world']
/*\B的场合*/
// 1. 查找所有非单词边界位置
console.log(str.replace(/\B/g, '|'));
// 输出: "H|e|l|l|o,| w|o|r|l|d|! 你|好 1|2|3 t|e|s|t|_1|2|3"// 2. 匹配单词内部的模式
console.log(str.match(/\B\w+\B/g));
// 匹配完全被单词字符包围的子串
// 输出: ['ell', 'orl', '23', 'est', '12']
// 解释: 匹配"Hello"中的"ell","world"中的"orl"等// 3. 查找相邻的相同单词字符
console.log(str.match(/(\w)\B\1/g));
// 匹配像"ll"、"oo"这样的重复字母

重复匹配

  • {n,}n次或更多

在贪婪量词后加 ?

  • +?尽可能少重复,至少1次
  • ??尽可能少重复,0或1次
  • {n,}?尽可能少重复,至少n次

分组与捕获

  • (?:pattern)非捕获分组(不保存匹配结果)
  • \1, \2, ...同一个正则表达式内引用前面捕获的分组
  • $1, $2, ...在替换字符串中引用分组
  • (?<name>pattern)给分组起个有意义的名称,提高可读性
  • 引用:\k<name>$<name>
/*引用分组*/
// 匹配重复的单词
let re1 = /\b(\w+)\b\s+\1\b/;
console.log(re1.test("hello hello"));  // true
console.log(re1.test("hello world")); // false/*替换引用分组*/
string.replace(regexp, replacement)
// 日期格式转换
let dateStr = "2024-01-15";
let re1 = /(\d{4})-(\d{2})-(\d{2})/;
console.log(dateStr.replace(re1, "$2/$3/$1"));  // "01/15/2024"/*命名分组*/
// 日期解析
let re1 = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
let match = re1.exec("2024-01-15");
console.log(match.groups.year);   // "2024"
console.log(match.groups.month);  // "01"
console.log(match.groups.day);    // "15"

补充2:正则表达式常见场景

/*邮箱*/
// 简单版本
let emailRe = /\S+@\S+\.\S+/;
// 复杂版本
let emailRe2 = /^[\w.%+-]+@[\w.-]+\.[a-zA-Z]{2,}$/;/*时间匹配(24小时制)*/
// 严格版本(必须两位数)
let timeRe = /^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/;/*电话匹配*/
// 简单电话格式
let phoneRe = /^(\d{3})-(\d{3,8})$/;/*提取尖括号内容*/
// 匹配 <内容>
let angleRe = /<([^>]+)>/;/*提取引号内容*/
// 匹配 "内容" 或 '内容'
let quoteRe = /(['"])(.*?)\1/;

补充3:转义规则总结与验证模式

字符 何时需要转义 示例
. 匹配点字符时 \.
* + ? {} 匹配量词字符本身时 \*\+
^ $ 匹配开始/结束字符本身时 \^\$
[ ] 匹配方括号本身时 \[\]
( ) 匹配圆括号本身时 \(\)
` ` 匹配或符号本身时
`` 匹配反斜杠本身时 \\
- 在字符组中且表示范围时 在开头/结尾或用\-

零宽断言

  • (?=pattern)正向前瞻(后面是pattern)
  • (?!pattern)负向前瞻(后面不是pattern)
  • (?<=pattern)正向后顾(前面是pattern)
  • (?<!pattern)负向后顾(前面不是pattern)

测试与验证模式test

// 或使用 test() 方法
if (re.test('测试字符串')) {console.log('测试通过');
} else {console.log('测试失败');
}

JSON

JavaScript Object Notation,一种超轻量级数据交换格式,JavaScript的一个子集。

对应JavaScript

JSON规定字符集必须是UTF-8,字符串必须用双引号"",Object的键也必须用双引号""

  • number:number
  • boolean:true+false
  • string:string
  • null:null
  • array:Array表示方式——[]
  • object:{ ... }表示方式。

序列化

JavaScript对象→JSON,把这个对象序列化成一个JSON格式的字符串。一个JSON格式的字符串,只需要把它反序列化成一个JavaScript对象,就可以在JavaScript中直接使用。

let xiaoming = {name: '小明',age: 14,gender: true,height: 1.65,grade: null,'middle-school': '\"W3C\" Middle School',skills: ['JavaScript', 'Java', 'Python', 'Lisp']
};let s = JSON.stringify(xiaoming);
console.log(s);

加上参数,按缩进输出

JSON.stringify(xiaoming, null, '  ');↓
{"name": "小明","age": 14,"gender": true,"height": 1.65,"grade": null,"middle-school": "\"W3C\" Middle School","skills": ["JavaScript","Java","Python","Lisp"]
}

若要筛选对象的键值,可以传入Array,这里选择姓名和技能

JSON.stringify(xiaoming, ['name', 'skills'], '  ');↓
{"name": "小明","skills": ["JavaScript","Java","Python","Lisp"]
}

还可以传入函数,这样对象的每个键值对都会被函数先处理

function convert(key, value) { // 所有属性值都变成大写if (typeof value === 'string') {return value.toUpperCase();}return value;
}JSON.stringify(xiaoming, convert, '  ');↓
{... // 省略"middle-school": "\"W3C\" MIDDLE SCHOOL","skills": ["JAVASCRIPT","JAVA","PYTHON","LISP"]
}

精确控制序列化,在对象内定义toJSON()直接返回JSON应该序列化的数据。

let xiaoming = {... // 其余属性toJSON: function () {return { // 只输出name和age,并且改变了key:'Name': this.name,'Age': this.age};}
};JSON.stringify(xiaoming); // '{"Name":"小明","Age":14}'

反序列化

JSON格式的字符串需要使用JSON.parse()把它变成一个JavaScript对象

JSON.parse('[1,2,3,true]'); // [1, 2, 3, true]
JSON.parse('{"name":"小明","age":14}'); // Object {name: '小明', age: 14}
JSON.parse('true'); // true
JSON.parse('123.45'); // 123.45//JSON.parse()还可以接收一个函数,用来转换解析出的属性
let obj = JSON.parse('{"name":"小明","age":14}', function (key, value) {if (key === 'name') {return value + '同学';}return value;
});
console.log(JSON.stringify(obj)); // {name: '小明同学', age: 14}

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询