JavaScript基础
在HTML中引入JavaScript
在网页中使用<script></script>标签插入Javascript代码。
document是JavaScript在浏览器中定义的一个对象,它表示HTML文档内容。
由于浏览器引擎解析网页源代码的顺序是从上到下的,考虑到HTML文档的DOM结构模型规范性,建议把JavaScript脚本写在<head></head>标签之间,或者写在<body></body>标签之间。
<html>
<head>
<script>
// JavaScript代码
</script>
</head>
<body>
<!-- 网页内容 -->
<script>
// JavaScript代码
</script>
</body>
</html>对于JavaScript脚本的插入位置,有以下3个位置:
<head>部分:将 JavaScript 放在页面的头部。这种方式会在页面内容加载之前就执行 JavaScript 代码。一般建议将各种公共函数和变量放在<head></head>标签内。<body>部分的顶部:将 JavaScript 放在页面内容的顶部。这种方式可以在内容加载之前执行 JavaScript 代码,但不会影响页面内容的加载。<body>部分的底部:将 JavaScript 放在页面内容的底部。这是推荐的做法,因为这样可以确保页面内容完全加载之后再执行 JavaScript 代码,从而避免页面加载缓慢的问题。
JavaScript也可以像CSS一样,以文件形式引入到HTML文档中,以达到复用脚本文件的目的。
通过给<script>标签添加src属性可以在当前页面中引入指定url路径的脚本文件。
<html>
<head>
<script src="./common.js"></script>
</head>
<body>
<button onclick="printToConsole('hello world')">hello world</button>
</body>
</html>JavaScript语法基础
JavaScript基本语法
- 语言编码:JavaScript语言建立在Unicode字符集上,因此脚本中可以使用双字节的字符命名常量、变量或函数,比如中文。但一般不建议使用中文命名变量。
- 大小写敏感:对于特定变量、类、构造函数等,首字母大写。对于普通变量、方法,使用驼峰式命名法。
- 分隔符:JavaScript一般会忽略分割符,如空格符、制表符和换行符。如需要在字符串、表达式中插入分割字符,可以转移分隔符。
\t表示制表符\n表示换行符\s表示空白符。 - 代码注释:使用
//实现单行注释,使用/**/实现多行注释。 - 标签:在JavaScript脚本中可以加上标签,标签在JavaScript程序进行快速定位。标签一般由一个合法的字符名称加上一个冒号组成,标签可以放在任意行的起始位置。可以在结构体中使用break、continue等跳转语句跳出循环结构。
标签一般用于多层循环时,在内层循环跳出到指定层循环。
<html>
<head>
<script>
function test() {
loop: for (var i = 0; i < 10; i++) {
for (var j = 0; j < 10; j++) {
for (var k = 0; k < 10; k++) {
console.log(i, j, k);
if (k == 5) {
continue loop;
}
}
}
}
}
</script>
</head>
<body>
<button onclick="test()">点我</button>
</body>
</html>- JavaScript关键字
| 关键字 | 说明 | |
|---|---|---|
| break | 终止整个循环 | |
| continue | 结束本次循环 | |
| switch | switch-case-default条件分支选择 | |
| case | switch-case-default条件分支选择 | |
| default | switch-case-default条件分支选择 | |
| throw | 抛出异常 | |
| try | try-catch-finally捕获异常并处理 | |
| catch | 捕获异常并处理 | |
| finally | 捕获异常并处理 | |
| do | do-while循环 | |
| while | do-while循环 | |
| for | for循环体 | |
| if | if-else条件分支 | |
| else | if-else条件分支 | |
| instanceof | 用于检查一个对象是否属于某个类的实例 | |
| typeof | 用于获取一个表达式的类型 | |
| var | 定义变量 | |
| void | 空类型 | |
| function | 声明函数 | |
| new | 实例化一个对象 | |
| return | 函数返回一个值 | |
| this | 关键字this用于引用当前执行上下文中的对象。this的值取决于代码在哪里被调用以及如何被调用。 | |
| in | 用于检查对象的属性是否存在于对象本身或其原型链中 | |
| delete | delete关键字用于删除对象的属性 | |
| with | 创建一个临时的作用域,用于简化多次访问同一个对象的属性的代码。在实际开发中不推荐使用 |
- JavaScript保留字
| 保留字 | 说明 |
|---|---|
| boolean | 声明布尔类型变量 |
| byte | 声明字节类型变量 |
| char | 声明字符类型变量 |
| short | 声明短整型类型变量 |
| int | 声明整型类型变量 |
| long | 声明长整型类型变量 |
| float | 声明单精度浮点型变量 |
| double | 声明双精度浮点型变量 |
| enum | 定义枚举类 |
| abstract | |
| class | |
| final | |
| const | 用于声明常量,确保了声明的变量在赋值后不能再被重新赋值。但如果用const声明一个对象,这个const是不能再指向其他对象的,但对象内的属性是可以被改变的。 |
| debugger | |
| export | |
| import | |
| extends | |
| implements | |
| interface | |
| native | |
| package | |
| private | |
| protected | |
| public | |
| static | |
| super | |
| synchronized | |
| throws | |
| transient | |
| volatitle | |
| goto |
JavaScript的常量
JavaScript提供了一些默认常量供开发使用,这些系统常量主要是数学和数值常量,方便数学运算和特殊值引用。包括:
Math.E:常量e,自然对数的底数。Math.LN10:10的自然对数。Math.LN2:2的自然对数。Math.LOG10E:以10为底的e的对数。Math.LOG2E:以2为底的e的对数。Math.PI:常量PI。Math.SQRT1_2:2的平方根除以1.Math.SQRT2:2的平方根。Number.MAX_VALUE:最大的数。Number.MIN_VALUE:最下的数。Number.NaN:非数字值。Number.NEGATIVE_INFINITY:负无穷大,溢出时返回该值。Number.POSITIVE_INFINITY:正无穷大,溢出时返回该值。
JavaScript的变量
JavaScript使用var关键字声明变量,声明变量有如下5中方式:
var a; //声明单个变量
var b,c;
var d=1;
var e=2,f=3;
var e=f=3; //声明并初始化多个变量,且定义变量的值相同声明变量后,在没有初始化之前,则它的初始值为undefined(未定义的值)。
变量的作用域
变量可分为全局变量和局部变量(私有变量)。
- 全局变量:在整个页面中可见,并在页面任何位置被允许访问。
- 不使用var、let、const关键字定义的变量会被自动提升为全局变量,不管在函数内还是函数外
- 局部变量:只能在指定函数内可见,函数外面不可见,也不允许访问。
- 在函数内部使用var关键字声明的变量就是私用变量
JavaScript的运算符
比较运算符
==:如果操作数相等,则返回真。在对比时会进行类型转换。===:如果操作数完全相等,则返回真。在对比时不进行类型转换。
"1"==1 //返回true,这里字符串1会转换成数字1,然后再进行比较。
"1"===1 //返回false,不进行类型转换,比较两个值类型不同,返回false。特殊运算符
?::条件三元运算符是一个简洁的替代 if...else 语句的方式。它的语法如下:
condition ? expression1 : expression2;
let message = (age >= 18) ? "成年人" : "未成年人";,(逗号):计算两个表达式,返回第二个表达式的值。
var a = (1 + 2, 3 + 4);
console.log(a); // 输出 7delete:允许删除一个对象的属性或数组中指定的元素。
delete object.property
delete object['property']
let person = {
name: 'John',
age: 30
};
console.log(person); // 输出 { name: 'John', age: 30 }
delete person.age;
console.log(person); // 输出 { name: 'John' }new:允许创建一个用户自定义对象类型或内建对象类型的实例。typeof:用于检测给定变量的数据类型。
let x;
console.log(typeof x); // "undefined"
let y = 10;
console.log(typeof y); // "number"
let z = "Hello";
console.log(typeof z); // "string"instanceof:用来检查一个对象是否是某个特定类型(或者是该类型的原型链上的对象)的实例。
function Person(name) {
this.name = name;
}
var person1 = new Person('Alice');
console.log(person1 instanceof Person); // true
console.log(person1 instanceof Object); // true(因为所有对象都是 Object 的实例)in:用于检查对象是否具有指定属性
let person = {
name: 'Alice',
age: 30
};
console.log('name' in person); // true
console.log('gender' in person); // falsevoid:用于执行表达式但不返回任何值。当使用void运算符时,表达式会被执行,但结果会被丢弃,返回的值始终是undefined。
<a href="javascript:void(0);" onclick="myFunction()">点击这里</a>
<script>
function myFunction() {
// 执行一些操作
}
</script>上面这段代码点击超链接后,执行myFunction函数,但void(0)返回undefined,网页不跳转。
.:对象属性存取。[]:数组下标。():函数调用,存入参数列表。
JavaScript语句
表达式语句和语句块
- 表达式尾部附加一个分号形成一个表达式语句
- 独立一行的表达式也是表达式语句,解析时会自动补加分号,但建议加上分号。
- 语句块使用大括号包围住。
var a,b.c;
{
a=b=c=1
a=b+c;
}条件语句
条件语句主要包含两种形式:if和switch语句。
- if语句
if(condition){
//do something
}
else{
//do something
}
if(condition){
//do something
}
else if(condition){
//do something
}
else{
//do something
}- switch语句:switch语句会首先计算switch关键字后面的表达式,然后再按出现的先后顺序计算case后面的表达式。再比较过程中使用的是严格相等运算符
===来比较值。
switch(expression){
case label1:
//do something
break;
case label2:
//do something
break;
default:
//do something
}<script>
var a = '1';
switch (a) {
case 1:
console.log("a=1");
break;
case '1':
console.log("a='1'");
break;
case 2:
console.log("a=2");
break;
default:
console.log("a!=1,'1',2");
}
</script>循环语句
- while语句
while (condition){
//do something
}
do{
//do something
}while (condition)- for语句
//1.for 循环:
//经典的for循环用于重复执行一段代码,通常使用计数器来控制循环的次数。
for (let i = 0; i < 5; i++) {
console.log(i);
}
//2。forEach 循环:
//forEach方法用于数组,遍历数组中的每一个元素。它无法中途跳出循环(例如使用break或continue)。
const array = [1, 2, 3, 4, 5];
array.forEach(element => {
console.log(element);
});
//3.for...in 循环:
//for...in循环用于遍历对象的可枚举属性(包括原型链中的属性)。在数组中使用时,它遍历的是数组的索引,而不是数组的值。
const object = {a: 1, b: 2, c: 3};
for (let key in object) {
console.log(key, object[key]);
//a 1
//b 2
//c 3
}
//4.for...of 循环:
//for...of循环用于遍历可迭代对象(如数组、字符串、集合等),直接获取值,而不是索引。
const array = [1, 2, 3, 4, 5];
for (let value of array) {
console.log(value);
}跳转语句
- break语句:退出循环或switch语句。
- continue语句:退出本次循环,继续下一次循环。
- return语句:返回表达式的值或从函数体内返回。
异常处理语句
try {
// 可能会抛出异常的代码
// throw new TypeError('这是一个类型错误');
throw new ReferenceError('这是一个引用错误');
} catch (error) {
if (error instanceof TypeError) {
console.error('捕获到类型错误:', error.message);
} else if (error instanceof ReferenceError) {
console.error('捕获到引用错误:', error.message);
} else {
console.error('捕获到其他错误:', error.message);
}
}
finally{
console.log("执行finally语句")
}在 JavaScript 中,一个 catch 块只能捕获一个异常对象,并且无法根据异常类型来匹配不同的 catch 块。通常使用 instanceof 运算符来判断捕获的异常对象的类型,并根据类型来执行相应的处理逻辑。
var语句
var语句用于声明一个或多个变量,在声明变量时可以进行初始化。默认状态下,被声明的变量初始值为underfined。
function语句
function语句用来定义函数。
function printStr(str){
console.log(str);
return 0;
}with语句
在JavaScript中,with语句可以用来简化多次访问同一个对象的情况。但是由于with语句会影响作用域链和性能,并且容易引起混淆和错误,因此在实际开发中并不推荐使用。
var person = {
name: 'Alice',
age: 30
};
with (person) {
console.log(name); // 相当于直接访问person.name
console.log(age); // 相当于直接访问person.age
}空语句
只有一个独立的分号的一行代码为空语句,起到占位但不执行代码的作用,在实际开发中不建议使用。
while(true){
;
}JavaScript数据类型
JavaScript是一种弱语言类型语言,在定义变量时不需要指定类型,一个变量可以存储任何类型的值。在变量运算时,JavaScript能自动转换数据类型。
在JavaScript中,数据有两种不同的存储方式,如下:
- 直接存储数据,称为值类型数据
- 存储数据的空间地址来间接保存数据,称为引用数据
值类型数据
JavaScript包含3种基本数据类型:数值、字符串和布尔值。
数值
数值类型不区分整型和浮点数,所有数值都为浮点型数值表示。
JavaScript中定义的特殊数值:
| 值 | 说明 |
|---|---|
| Infinity | 无穷大 |
| NaN | 非数值 |
| Number.MAX_VALUE | 可表示的最大数值 |
| Number.MIN_VALUE | 可表示的最小数值 |
| Number.NaN | 非数值 |
| Number.POSITIVE_INFINITY | 正无穷大 |
| Number.NEGATIVE_INFINITY | 负无穷大 |
| 数值类型分为:number和bigint。 |
- number:是双精度 64 位浮点数,表示的最大整数值约为9007199254740991。超出这个范围的整数可能会丢失精度。
- bigint:用于表示任意大小的整数,能够表示比number更大的整数。
bigint是ES2020标准引入的,低版本无法使用。
字符串
字符串由Unicode字符、数字、标点符号等组成的字符序列,必须使用单引号或双引号包括起来。
单引号可以包含双引号,双引号可以包含单引号,所有字符应该在同一行内书写完毕。
<script>
var str = "这是一段字符串";
var intStr = "12345";
var floatStr = "3.14";
//将字符串转换成数值类型
var intNumber = parseInt(intStr);
var floatNumber = parseFloat(floatStr);
var result = intStr * floatStr;
console.log(typeof (result));//两个字符串会自动转换为数值类型,然后进行运算,最后的结果是数值类型
</script>布尔值
布尔值数据仅包含2个值:true和false,分别表示逻辑的真和假。
要把任何值转换为布尔型数据,在值得前面增加两个叹号即可
var a=100;
var c=!!a; //将变量a转换为布尔值其他类型与布尔值的转换规则:
- 任何非0数字转换为布尔值后为true,而0转换为布尔值后为false。
- 任何非空字符串转换为布尔值后为true,而空格转换为布尔值为false。
- 如果把布尔值转换为字符串,则true转换为"true",false转换为"false"。
- 布尔值true转换为数字为1,false转换为数字为0。
以下这些值转换布尔值为false
0 //Number
NaN //Number
' ' //String
false //Bolean
null //Object
undefined //Undefinednull和undefined
- null:表示空值,当对象为空,或者变量没有引用任何对象,其返回值为null。typeof运算符返回object,说明它是一个特殊的对象。
- undefined:表示未定义的值。当变量未初始化时,会默认其值为undefined。typeof运算符返回undefined。
引用型数据
引用类型包括:数组、对象和函数等。
函数
定义函数
定义函数的方法有两种:
- 使用function语句声明函数
function定义函数又分为两种:
- 命名函数、声明式函数
- 匿名函数、引用式函数、函数表达式
//方式1 命名函数
function add(a, b) {
return a + b;
}
//方式2 匿名函数
var add = function(a, b) {
return a + b;
}- 通过Function对象来构造函数
//方式3 使用Function对象来构造函数
var add = new Function('a', 'b', 'return a + b');这种语法形式中,前面的每个参数都是一个函数参数,最后一个参数式函数主体,每一个参数都必须是字符串。
调用函数
调用函数使用小括号运算符来实现,括号内包含多个参数,参数通过逗号进行分隔。
//调用函数
add(2, 3); // 返回 5函数参数
函数的参数分为形参和实参
- 形参:就是定义函数时,传递给函数的参数,被称为形参。
- 实参:就是当函数被调用时,传给函数的参数,这些参数被称为实参。
//定义函数
function add(a, b) { //形参
return a + b;
}
//调用函数
add(2, 3); // 返回 5 //实参一般情况下,函数的形参和实参的个数是相等的,但是JavaScript没有规定两者必须相等。如果形参数大于实参时,则多出的形参值为undefined;相反,如果实参大于形参,则多出的实参就无法被形参变量访问,会被忽略掉。
函数形参的数量可以通过函数的length属性获取。
function add(a, b) { //形参
return a + b;
}
add.length; //2JavaScript也定义了Arguments对象,利用该对象可以快速操纵函数的实参,其length属性可以获取传入的实参数量,使用数组下标可以获取传入的每个参数值。
function walk(a,b,c) {
walk.length; // 返回函数定义的形参数量
arguments.length; // 返回传入的实参数量
console.log('第一个参数为:',arguments[0])
}函数的应用
- 匿名函数:匿名函数就是每次名称的函数,相当于一个复杂的表达式。当只需要一次性使用函数时,使用匿名函数更加有效率。
//匿名函数
var z = function (a, b) {
return (a + b) / 2;
}(1, 3); //返回4- 函数作为值:函数实际也是一种结构复杂的数据,因此可以把函数作为值赋予给其他变量。
//将函数作为值赋予给变量
var func = function (a, b) {
return (a + b) / 2;
}
alert(func(1, 3));- 函数作为参数:函数即可以赋值给变量,也可以作为实参赋值给函数。
//函数作为参数
var f1 = function (f, a, b) {
return f(a, b);
}
var f2 = function (a, b) {
return (a + b) / 2;
}
alert(f1(f2, 1, 3));//返回2- 函数作为表达式:函数可以参与到表达式运算中。
//函数作为表达式
(function (x) {
alert(x)
})(50);//提示为50闭包函数
闭包函数是指在一个函数内部再定义一个或多个函数与变量。闭包函数内定义的函数称为内部函数,闭包函数本身成为外部函数。在外部函数内定义的变量为私有变量,也称为外部变量。
闭包函数有如下特点:
- 内部函数可以访问外部函数的变量。
- 外部函数的变量在内部函数执行完毕后不会被销毁,因为内部函数仍然保持对这些变量的引用。
- 外部函数的变量可以被多个内部函数共享和修改。
//闭包函数
function outer() {
var a = 0;
function inner(m) {
a = a + m;
return a;
}
return inner;
}
var func = outer();
func(3); //初始调用,返回的是3
func(3); //再次调用,返回的是6箭头函数
箭头函数示例:
const func=(a,b)=>{return a+b;}箭头函数相当于是一个多条语句组合一起的表达式,箭头函数不会创建自己的 this。它会捕获上下文中定义时的 this,因此适合在需要保留上下文绑定的回调函数中使用。
对象(Object)
对象是面向对象编程的核心概念,它是已经命名的数据集合,是一种更复杂的数据结构。
创建对象
在JavaScript中创建对象有两种方式:
- 通过new运算符,调用对象的构造函数,生成对象实例。
//使用new生成对象实例
var date = new Date();
var o = new Object();- 使用对象直接量构造对象。对象直接量由一个列表构成,这个列表的元素由用冒号分隔开的属性:值对组成,元素之间使用都好逗号间隔开,整个列表使用包含在大括号内。
//对象直接量
var point = { //定义对象实例
x: 1,
y: 2
}访问对象
访问对象属性的方式有两种:
- 使用点号
.运算符,直接访问对象的属性和嵌套对象的属性,使用关键字this来引用当前对象实例。
var player = {
transform: {
x: 1,
y: 2
},
health: 100,
run: function () {
this.transform.x++;
this.transform.y++;
}
}
player.run();
alert(player.transform.x);//返回2- 通过集合运算符
[]来访问对象的属性,使用字符串下标来表示属性。
//使用[]来访问对象的属性
var player = {
transform: {
x: 1,
y: 2
},
health: 100,
run: function () {
this.transform.x++;
this.transform.y++;
}
}
player["run"]();
alert(player["transform"]["x"]);//返回2数组
对象是无序的数据集合,而数组是一组有序数据的集合,它们之间可以互相转换,但是数组拥有大量的方法,适合完成一些复杂的运算。
定义数组
定义数组有多种方法:
- 使用构造函数Array()。
//使用Array定义数组
var arr = new Array();//定义一个空数组
var arr = new Array(1, 2, 3, "4", "5", "6");//参数表示数组中的每一个元素值
var arr = new Array(6);//指定数组元素个数,元素的初始值为undefined
var arr = Array(6);//定义数组时可以省略new运算符- 使用
[]定义数组直接量。使用数组直接量定义数组要比使用Array()函数定义数组速度要快,操作更方便。
//使用[]数值直接量定义数组
var arr = [11, 2, 3, "4", "5", "6"]存取元素
- JavaScript使用
[]加元素下标存取数组元素,通过length属性获取数组长度,修改length属性动态增加或删除数组元素,使用delete运算符可以删除数组元素的值,但不会改变数组的length属性的值。
var arr = [11, 2, 3, "4", "5", "6"]
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
delete arr[0];//第一个元素会变成undefined
arr.length = 3;
console.log(arr);//数组长度缩短为3- 使用
push()和pop()方法操作数组尾部。
- push():可以向数组的末尾插入一个或多个元素,返回操作后数组的长度。
- pop():可以从数组的末尾删除一个元素,并返回数组中最后一个元素的值。
var arr = [1];
console.log(arr.push(11, 2, 3, "4", "5", "6"));//返回7
console.log(arr.pop());//返回6- 使用unshift()和shift()方法操作数组的头部。
- unshift():可以向数组的头部插入一个或多个元素,返回操作后数组的长度。
- shift():可以从数组的头部删除一个元素,返回数组中第一个元素的值。
var arr=[1];
console.log(arr.unshift(11, 2, 3, "4", "5", "6"))//返回7
console.log(arr.shift());//返回11- 使用splice()方法截取、删除、插入数组元素。方法包含3个参数,第一个参数指定操作元素的起始位置,第二个参数指定要操作的元素个数,第三个参数表示插入的具体元素。
splice()方法的操作流程是,根据第一、二参数截取并删除数组的元素,插入第三个参数的元素到指定位置,然后返回被截取的元素。
var arr = [11, 2, 3, "4", "5", "6"];
var subArr = arr.splice(2, 2, [99, 98],97);
console.log(subArr);//subarr为[3,"4"]
console.log(arr);//arr更新为[11,2,[99,98],97,"5","6"]数组应用
- 数组与字符串的转换。
- 使用Array对象的join()方法可以把数组转换为多种形式的字符串,join()方法接受一个参数,用来定义合并元素的连字符,默认为以逗号连接每个元素。
var arr=[1,2,3,4,5];
console.log(arr.join("-"));//输出1-2-3-4-5- 使用字符串的**split()**方法可以把字符串劈开为一个数组,该方法包含两个参数,第一个参数指定劈开的分隔符,第二个参数指定返回数组的长度。
var arr = [1, 2, 3, 4, 5];
var str = arr.join("-");
console.log(str);//输出1-2-3-4-5
console.log(str.split("-"));//输出1,2,3,4,5- 数组的排列顺序
- Array的**reverse()**方法可以颠倒数组元素的顺序,该方法是在原数组基础上进行操作的,不会新建数组,方法返回当前数组。
var arr = [1, 2, 3, 4, 5];
arr.reverse();
console.log(arr);//输出5,4,3,2,1- 使用**sort()**方法可以对数组进行排序,sort()可以接受一个函数作为参数,并按照其参数进行排序。如省略参数,则按默认规则进行排序。
var arr = [5, 7, 1, 6, 8, 4];
arr.sort();
console.log(arr);//输出1,4,5,6,7,8- 连接数组
- Array对象的**concat()**方法可以实现将参数追加到指定数组中,形成一个新的连接数据。如果参数中包含数组,则把数组元素展开添加到数组中(只展开一次)。
var arr = [5, 7];
newArr = arr.concat([6, 2, 1], [3, [4, 8, 9]]);
console.log(newArr);//输出5,7,6,2,1,3,[4,8,9]- 截取子数组
- Array对象的**slice()**方法返回数组中指定的片段,该方法接收两个参数,指定截取数组的起止点,第一个参数包含在截取范围内,第二个参数不包含在范围内。第二个参数省略的时候表示截取到数据末尾。
var arr = [1, 2, 3, 4, 5];
console.log(arr.slice(2));//输出3,4,5
console.log(arr.slice(2, 4));//输出3,4集合常用操作
JavaScript 提供了多种用于处理集合(数组、对象等)的方法:
map():用于对数组中的每个元素进行操作,并返回一个新数组。
const numbers = [1, 2, 3, 4];
const doubled = numbers.map(n => n * 2);
console.log(doubled); // [2, 4, 6, 8]- filter():用于过滤数组中的元素,返回满足条件的元素组成的新数组。
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter(n => n % 2 === 0);
console.log(evenNumbers); // [2, 4]- reduce():用于累加数组中的元素,返回一个累积的结果。reduce() 可以用于数组的求和、求积等操作。
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // 10- forEach():用于遍历数组,对每个元素执行指定的操作。与 map() 不同的是,forEach() 不返回新数组。
const numbers = [1, 2, 3, 4];
numbers.forEach(n => console.log(n * 2));
// 输出: 2, 4, 6, 8- find():返回数组中第一个满足条件的元素。如果没有找到满足条件的元素,返回 undefined。
const numbers = [1, 2, 3, 4];
const firstEven = numbers.find(n => n % 2 === 0);
console.log(firstEven); // 2- findIndex():返回数组中第一个满足条件的元素的索引。如果没有找到满足条件的元素,返回 -1。
const numbers = [1, 2, 3, 4];
const index = numbers.findIndex(n => n % 2 === 0);
console.log(index); // 1- some():测试数组中是否至少有一个元素满足指定条件,返回布尔值。
const numbers = [1, 3, 5];
const hasEven = numbers.some(n => n % 2 === 0);
console.log(hasEven); // false- every():测试数组中是否所有元素都满足指定条件,返回布尔值。
const numbers = [2, 4, 6];
const allEven = numbers.every(n => n % 2 === 0);
console.log(allEven); // true- sort():对数组进行排序,默认按照字符串顺序。可以通过提供比较函数来实现自定义排序。
const numbers = [4, 2, 3, 1];
const sorted = numbers.sort((a, b) => a - b);
console.log(sorted); // [1, 2, 3, 4]- flat():将嵌套的数组“拉平”成一个新数组。
const arr = [1, [2, [3, [4]]]];
const flattened = arr.flat(2);
console.log(flattened); // [1, 2, 3, [4]]- flatMap():先对数组中的每个元素进行操作,然后将结果“拉平”成一个新数组。
const arr = [1, 2, 3];
const result = arr.flatMap(n => [n, n * 2]);
console.log(result); // [1, 2, 2, 4, 3, 6]JavaScript数据类型检测
| 值 | typeof value(表达式返回值) | value.constructor(构造函数的属性值) |
|---|---|---|
var value=1 | "number" | Number |
var value="a" | "string" | String |
var value=true | “boolean” | Boolean |
var value={} | "object" | Object |
var value=new Object() | "object" | Object |
var value=[] | "object" | Array |
var value=new Array() | "object" | Array |
var value=function(){} | "function" | Function |
function className(){} | "object" | className |
JavaScript数据类型自动转换
JavaScript能够自动转换变量的数据类型,这种转换是一种隐性行为。在自动转换数据类型时,JavaScript一般遵循:如果某个类型的值被用于需要其他类型的值的环境中,JavaScrpit会自动将这个值转换成所需要的类型。
简单点说,JavaScrpt会根据环境对值的类型的需求对值的类型进行自动转换。
| 值 | 字符串操作 | 数字运算环境 | 逻辑运算环境 | 对象操作环境 |
|---|---|---|---|---|
| undefined | "undefined" | Nan | false | Error |
| null | "null" | 0 | false | Error |
| 非空字符串 | 不转换 | 字符串对应的数字值或NaN | true | String |
| 空字符串 | 不转换 | 0 | false | String |
| 0 | "0" | 不转换 | false | Number |
| NaN | "NaN" | 不转换 | false | Number |
| Infinity | "Infinity" | 不转换 | true | Number |
| Number.POSITIVE_INFINITY | “Infinity” | 不转换 | true | Number |
| Number.NEGATIVE_INFINITY | "Infinity" | 不转换 | true | Number |
| Number.MAX_VALUE | "1.7976931348623157e+308" | 不转换 | true | Number |
| Number.MIN_VALUE | "5e-324" | 不转换 | true | Number |
| 其他所有数字 | “数字的字符串值” | 不转换 | true | Number |
| true | "true" | 1 | 不转换 | Boolean |
| false | "false" | 0 | 不转换 | Boolean |
| 对象 | toString() | valueOf() 或toString()或NaN | true | 不转换 |
操作BOM
什么是BOM?
BOM 是浏览器对象模型**(Browser Object Model)**的缩写。它是指浏览器提供的一组对象,用于访问和操作浏览器窗口及其各个组成部分,比如浏览器窗口本身、地址栏、历史记录等。
BOM 并不是 W3C 标准规范的一部分,而是由浏览器厂商根据自己的实现和需求提供的。
BOM 中包含了一些常用的对象,比如 window、navigator、screen、history、location 等,开发者可以使用这些对象来获取浏览器窗口的尺寸、用户的屏幕分辨率、浏览器的历史记录以及当前页面的 URL 等信息,也可以通过 BOM 对象来操作浏览器窗口的大小、位置以及跳转到其他页面等操作。
window对象
通过window对象可以访问浏览器窗口,同时与浏览器相关的其他客户端对象都是window的子对象。各个对象之间存在着一种树形结构关系,其中window对象代表根节点。其结构图如下: 
- window:客户端JavaScript的顶层对象,每当
<body>或<frameset>标签出现时,window对象就会被自动创建。 - navigator:包含客户端有关浏览器的信息。
- screen:包含客户端显示屏的信息。
- history:包含浏览器窗口访问过的URL信息。
- location:包含当前网页文档的URL信息。
- document:包含整个HTML文档、可被用来访问文档内容,及其所有页面元素。
假如你要访问document对象,只需要使用点号.引用,如下操作:
var document=window.document; //获取document对象window的全局作用域特性
- window对象提供了全局作用域,window对象为全局对象,因此所有的全局变量都被设为该对象的属性。反过来,该对象的属性都为全局变量。
var a = "window.a";//定义全局变量a
function f() {
alert(a);//弹出a的值
}
f();//弹出"window.a"
alert(window.a);//弹出"window.a"- 但是全局变量与window直接定义的属性有一点不同,全局变量不能通过delete运算符删除,而window对象可以。这是因为使用var声明全局变量时,window会为这个属性定义一个名为'configurable'的特性,这个值被设置为false,该属性则不能被delete运算符删除。
var a = "a";
window.b = "window.b";
alert(delete a); //弹出false
alert(delete window.b); //弹出true
alert(a); //弹出"a"
alert(window.b); //弹出"undefined"window对象提供的系统测试方法
window对象定义了3个人机交互的接口方法,这3个方法一般用于对JavaScript进行测试,不建议用在生产环境。
- alert():由浏览器向用户弹出提示性信息。该方法接收一个可选参数,表示弹出的提示性内容。
- confirm():由浏览器向用户弹出包含提示性信息的对话框,对话框包含两个按钮:确认和取消按钮。该方法接收一个可选参数,表示弹出的提示性信息。用户点击确认返回true,点击取消返回false。
- prompt():由浏览器向用户弹出包含提示信息的对话框,对话框包含一个可输入的文本框用于接收用户的输入,返回用户输入的信息。 通过这几个方法打开的对话框都是同步和模态的,也即显示这些对话框的时候,javascript代码会停止执行。只有关掉对话框后才会恢复执行。所以这些方法比较适合用于测试,在生产环境应避免使用。
window对象打开、关闭窗口
打开新窗口window.open()
使用window对象的open()方法,可以打开一个新窗口,用法如下:
window.open(url,name,features,replace);- url:表示新窗口要显示的文档url路径。如果省略,则打开空白页。
- name:可选字符串,声明新窗口的名称,或指定一个已经存在的窗口打开。使用该参数时,features参数会被忽略。该参数提供了一些固定值:
_blank:在新标签页打开,默认值。_self:在当前标签页打开。_parent:在父级框架中打开。_top:在顶级框架中打开。
- features:可选字符串,声明新窗口要显示的标准浏览器特征。
- replace:可选布尔值,规定了新URL时在浏览器中创建一条新纪律还是替换浏览器历史中的当前值。
//在新标签打开一个宽500、高400的百度网站
var w=window.open("https://baidu.com/","_blank","width=500,height=400")opener属性
新创建的window对象拥有一个opener属性,它保存着打开它的原始窗口对象。这个属性有以下作用:
- 可以通过这个属性在新window对象和旧window对象之间进行通信。
- 当opener被设置为null,新标签将在单独的进程中运行,这样新创建的标签页就无法与打开它的标签页通信。标签页之间的通讯,一旦切断,将无法再恢复。
var w=window.open();
window.opener=null;关闭窗口window.close()
window对象的close()方法可以关闭一个窗口,closed属性可以检测当前窗口是否关闭,如已关闭则返回true,否则返回false。
try {
var w = window.open("http://www.baidu.com");
} catch (e) {
alert("浏览器禁止弹出窗口");
}
w.close();//关闭一个窗口
setTimeout(function () {
if (w.closed) {
alert("创建的窗口已经关闭");
}
}, 1);框架集
框架集已经被HTML5废弃,现代Web开发中推荐使用CSS和JavaScript来实现类似的布局效果,比如使用Flexbox、Grid布局或者响应式设计。
在框架集中,每个框架实际上都对应着一个 window 对象。当我们在一个框架中执行 JavaScript 代码时,实际上是在该框架对应的 window 对象中执行的。每个框架都有自己的 window 对象,它们之间是相互独立的,可以通过 window 对象来访问和操作各自的文档内容和属性。
控制窗口位置
- 在IE、Safari、Opera和Chrome浏览器下,window对象支持screenLeft和screenTop属性,通过该属性获取窗口屏幕坐标和上边的位置。
- 在Firefox浏览器下,window对象支持screenX和screenY属性获取窗口位置。
console.log(window.screenLeft, window.screenTop);
console.log(window.screenX, window.screenY);使用window对象的moveTo()和moveBy()方法可以将窗口精确地移动到一个新位置。
moveTo():接收新位置的x和y坐标值。moveBy():接收水平和垂直方向上移动的像素数。
需要注意的是,通过这两个方法在浏览器会被禁止,并且仅适用于最外层的window对象。
控制窗口大小
window对象提供了一些属性用于确定窗口的大小。
- innerWidth:页面视图宽度
- innerHeight:页面视图高度
- outerWidth:浏览器窗口宽度
- outerHeight:浏览器窗口高度
window.innerWidth;//665
window.innerHeight;//598
window.outerWidth;//681
window.outerHeight;//727document对象页提供了一些属性用于用户页面视图的大小
- document.documentElement.clientWidth:保存页面宽度
- document.documentElement.clientHeight:保存页面高度
document.documentElement.clientWidth;//648
document.documentElement.clientHeight;//581window对象定义了resizeBy()和resizeTo()方法,用于调整窗口大小。
resizeBy():方法用于根据当前窗口的大小调整窗口的宽度和高度,接收两个参数,分别代表要调整的宽度和高度的增量(以像素为单位)。resizeTo():方法用于将浏览器窗口调整为指定的宽度和高度 window对象的scrollBy()和scrollTo()方法用于控制浏览器窗口的滚动位置scrollTo():接受两个参数,分别是要滚动到的水平位置和垂直位置,绝对位置。scrollBy():接受两个参数,分别是要相对于当前滚动位置滚动的水平距离和垂直距离。
window.scrollTo(10,10);//页面滚到到左上角10,10的位置
window.scrollBy(10,-10);//页面向右滚到10,向上滚到10window对象的focus()和blur()用于处理元素获取焦点和失去焦点,调用对象为元素。
foucs():用于让指定的元素获得焦点。blur():用于让指定的元素失去焦点。
document.getElementById("kw").focus();
document.getElementById("kw").blur();使用定时器
window对象包含4个定时器专用方法,用于实现代码定时执行或周期执行,分别如下:
- setInterval():按照指定的周期(以毫秒为单位)来调用函数或计算表达式。
- setTimeout():在指定的毫秒数后调用函数或计算表达式。
- clearInterval():取消由setInterval()方法生成的定时器对象。
- clearTimeout():取消由setTimeout()方法生成的定时器对象。
setTimeOut()
setTimeOut()方法能够在指定时间段后执行特定的代码,方法会返回一个定时器对象。
var o=setTimeOut(code,delay);- code:表示要延迟执行的代码字符串或函数
- delay:表示延迟时间,以毫秒为单位计算。
<html>
<head>
</head>
<body>
<div id="div1">div1</div>
<div id="div2">div2</div>
<div id="div3">div3</div>
<script>
var o = document.getElementsByTagName("body")[0].children;
for (var i = 0; i < o.length; i++) {
o[i].onmouseover = function (i) {
return function () {
setTimeout(function () {
alert(o[i].id);
}, 1000);
}
}(i);
}
</script>
</body>
</html>以上示例实现了,鼠标经过div元素时,设置一个定时器,延迟1000毫秒后,alert弹出元素的id值。
clearTimeout(out);//清除定时器setInterval()方法
使用setIntervar()方法能够周期性执行指定的代码,直到浏览器窗口关闭,或者跳转到其他页面为止。
var o=setInterval(code,interval);- code:表示要周期执行的代码字符串或方法。
- interval:周期执行的时间间隔。
<html>
<head>
</head>
<body>
<div id="div1">div1</div>
<div id="div2">div2</div>
<div id="div3">div3</div>
<script>
var o = document.getElementsByTagName("body")[0].children;
for (var i = 0; i < o.length; i++) {
o[i].onclick = function (i) {
return function () {
setInterval(function () {
console.log(o[i].id)
}, 1000);
}
}(i);
}
</script>
</body>
</html>以上代码实现了当点击div标签后,启动一个定时任务,持续输出日志。
navigator对象
navigator对象包含了浏览器的基本信息,如名称、版本和系统信息等,通过window.navigator可以获取该对象的引用。
navigator对象的常用属性如下:
| 属性 | 描述 |
|---|---|
| appCodeName | 返回浏览器的代码名 |
| appMinorVersions | 返回浏览器的次级版本 |
| appName | 返回浏览器的名称 |
| appVersion | 返回浏览器的平台和版本信息 |
| browserLanguage | 返回当前浏览器的语言 |
| cookieEnabled | 返回指明浏览器中是否启用cookie的布尔值 |
| cpuClass | 返回浏览器系统的CPU登记 |
| onLine | 返回指明系统是否处于脱机模式的布尔值 |
| platform | 返回运行浏览器的操作系统平台 |
| systemLanguage | 返回OS使用的默认语言 |
| userAgent | 返回由客户机发送服务器的user-agent头部的值 |
| userLanguage | 返回OS的自然语言设置 |
| plugins | 以数组形式返回浏览器已安装的插件列表 |
console.log("appCodeName:", navigator.appCodeName);
console.log("appMinorVersions:", navigator.appMinorVersions);
console.log("appName:", navigator.appName);
console.log("appVersion:", navigator.appVersion);
console.log("browserLanguage:", navigator.browserLanguage);
console.log("cookieEnabled:", navigator.cookieEnabled);
console.log("cpuClass:", navigator.cpuClass);
console.log("onLine:", navigator.onLine);
console.log("platform:", navigator.platform);
console.log("systemLanguage:", navigator.systemLanguage);
console.log("userAgent:", navigator.userAgent);
console.log("userLanguage:", navigator.userLanguage);
浏览器检测方法
浏览器检测的方法有很多中,常用方法包括两种:特征检测法和字符串检测法。
- 特征检测法:该方法根据浏览器是否支持特定功能来决定操作的方式。这个一种非精确判断法,但是最新安全的检测方法。
其原理是,当使用一个对象、方法或属性时,先判断它是否存在。如果存在,则说明浏览器支持,可以放心使用。如不存在,它会返回undefined,则表示不支持。
//特征检测法 兼容各种浏览器
if (document.getElementById) {
var a = document.getElementById('test');
}
else if (document.getElementsByTagName) {
var a = document.getElementsByTagName('div')[0];
}- 字符串检测法:该方法使用navigator对象的userAgent属性,获取客户端浏览器的类型信息,再根据这个信息去做兼容。
window.navigator.userAgent;
//或
navigator.userAgent;检测客户操作系统
可通过navigator.userAgent的返回字符串,从中获取到关于操作系统的基本信息
检测插件
可通过navigator.plugins属性获取一个数组,数组中包含了安装的插件信息,其中每个元素包含下列属性:
- name:插件的名字。
- description:插件的描述。
- filename:插件的文件明。
- length:插件所处理的MIME类型数量。
location对象
location对象存储当前页面与位置(URL)相关的信息,表示当前显示文档的Web地址,使用window对象的location属性可以访问。
location对象的属性
location对象定义了8个属性,其中7个属性分别指向当前URL的各部分信息,另一个属性则包含完整的URL信息。
| 属性 | 说明 |
|---|---|
| href | 声明当前显示文档的完整URL。把该属性设置为新的URL会使浏览器读取并显示新URL的内容 |
| protocol | 声明url的协议部分,如http、https |
| host | 声明url的主机名和端口部分,如www.baidu.com:80 |
| hostname | 声明url的主机名,如www.baidu.com |
| port | 声明url的端口部分,如80 |
| pathname | 声明url的路径部分,如:/newspage/data |
| search | 声明url的查询部分,包括前导问好,如:?id=123&name=456 |
| hash | 声明url中锚部分,包括前导符(#),如:#top |
使用location实现网页跳转
location对象的属性都是可读可写的,如果改变了文档的location.href属性值,则浏览器会载入新的页面。如果改变了location.hash属性值,则页面会跳转到新锚点,而不会发生重载。
//以下两种方式都会使浏览器发生跳转
location="https://www.baidu.com";
location.href="https://www.baidu.com";除此之外,location对象还定义了两个方法:
reload():可以重新装载当前文档。replace():可以装载一个新文档而无须为它创建一个新的历史记录。也就是说,再浏览器的历史列表中,新文档将替换当前的文档。这样再浏览器中就不能够通过【返回】按钮返回当前的文档了。
window.location与document.location
window.location返回的信息虽然与document.location返回的信息相同,但其本质不相同。
- window.location返回的式location对象的引用,而document.location只是一个包含只读字符串的对象。
- 在服务器重定向时,document.location包含已经装载的URL。而window.location.href包含原始请求的文档URL
history对象
history对象存储浏览器窗口的浏览历史,通过window对象的history属性可以访问该对象。
history对象存储了最近访问的、有限条目的URL信息,存储的是当前窗口的历史记录,当创建新窗口时,历史记录为空。
现代浏览器为了保护客户端信息的安全和隐私,history对象通常被禁止通过JavaScript脚本直接访问其信息。
因此,history提供了多个方法访问历史记录列表中的URL,通过length可以获取URL的个数,方法如下:
back():与浏览器的向后按钮功能相一致,返回到前一个URL。forward():与浏览器的向前按钮功能相一致,访问下一个URL。go():根据参数决定可访问的URL。- 当参数为正整数,从历史列表中向前移动访问URL。
- 当参数为负整数,从历史列表中向后移动访问URL。
- 当参数为字符串时,会检索包含字符串的URL。
history.back();
history.forward();
history.go("baidu");
history.go(-1);在框架中时,使用frames加下标访问历史记录,如下所示,n为框架的下标位置。
frames[n].history.back();
frames[n].history.forward();
frames[n].history.go("baidu");
frames[n].history.go(-1);screen对象
window.screen对象存储客户端屏幕信息,这些信息可以用来探测客户端硬件的基本配置,利用screen对象可以优化程序设计,满足不同用户的显示要求。
screen对象提供了以下一些属性:
| 属性 | 描述 |
|---|---|
| availHeight | 返回显示屏幕的高度(不含Windows任务栏的部分) |
| availWidth | 返回显示屏幕的宽度(不含Windows任务栏的部分) |
| bufferDepth | 设置或返回调色板的比特深度 |
| colorDepth | 返回目标设备或缓冲器上的调色板的比特深度 |
| deviceXDPI | 返回显示屏幕的每英寸水平点数 |
| deviceYDPI | 返回显示屏幕的每英寸垂直点数 |
| fontSmoothingEnabled | 返回用户是否在显示控制面板中启用了字体平滑 |
| height | 返回显示屏幕的高度 |
| width | 返回显示屏幕的宽度 |
| logicalXDPI | 返回显示屏幕每英寸的水平方向的常规点数 |
| logicalYDPI | 返回显示屏幕每英寸的垂直方向的常规点数 |
| pixelDepth | 返回显示屏幕的颜色分辨率(比特每像素) |
| updateInterval | 设置或返回屏幕的刷新率 |
document对象
在浏览器窗口window对象中,都会包含一个document属性,该属性引用了窗口中显示的HTML文档的document对象。
document包含了文档的各种节点,如表单、图像、链接等信息,它们共同构成了文档对象模型。 
访问document内对象的方式
浏览器在加载文时,会自动构建文档对象模型,并文档内的对象映射到一个个集合中去,我们可以通过对象的属性的方式引用这些集合。
这些集合如下:
document.anchors:返回所有带name属性的<a>标签。document.applets:返回所有<applet>标签。document.forms:返回所有Form对象,相当于document.getElementsByTagName("form")。document.images:返回所有Image对象,相当于document.getElementsByTagName("img")。document.links:返回所有Area和Link对象,即所有带href特性的<a>标签。
对于Form、Image、Applet对象,还可以直接通过它们的name属性引用。
<img name="abc" scr="abc.gif"/>
<script>
console.log(document.abc.scr);//输出abc.gif
</script>动态生成文档内容
使用document的write()和writeln()方法可以动态生成文档内容,包括以下两种方式:
- 在浏览器解析时动态输出信息
- 在调用时间处理函数时使用write()和writeln()方法生成文档内容。
这两种方式的区别是:
- 第一种方式是在文档第一次加载添加文档信息。
- 第二种方式,是文档加载完成后,调用事件处理函数时生成文档内容,并且覆盖原文档内容。
write()和writeln()函数的区别是,writeln()会在输出的内容后面添加一个换行符,由于html忽略换行符,因此很少使用这个方法。
<script>
function f() {
document.write("<h1>Hello World!</h1>");
}
document.write('<p onclick="f()">点击这里</p>');
</script>操作DOM
DOM(Document Object Model,文档对象模型)是W3C制定的一套技术规范,用来描述Javascript脚本如何于HTML或XML文档进行交互的Web标准。
DOM的版本历史
- DOM 1级:1998年10月推出,包含DOM Core和DOM HTML。
- DOM 2级:2003年1月推出,包含DOM2 Core、DOM2 HTML、DOM2 Events、DOM2 Style、DOM2 Traversal、DOM2 Range、DOM2 Views。
- DOM 3级:2004年4月推出,包含DOM3 Core、DOM3 Load and Save、DOM3 Validation。
DOM中的节点
节点Node接口是构成HTML文档的基本单位,包含了元素节点、属性节点、文本节点、注释节点、文档节点、文档类型节点等,所有的节点类型都继承了Node接口。它们之间存在着父子、兄弟等关系。Javascript提供了多种方法访问和操作DOM节点,这允许我们动态地修改网页内容和结构。
节点类型nodeType
通过节点的nodeType属性,可以判断一个节点属于什么类型,说明如下:
| 节点类型 | 说明 | noteType值 | 常量名 |
|---|---|---|---|
| Element | 表示元素 | 1 | ELEMENT_NODE |
| Attr | 表示属性 | 2 | ATTRIBUTE_NODE |
| Text | 表示元素或属性中的文本内容 | 3 | TEXT_NODE |
| CDATASection | 表示文档中的CDATA区段,其包含的文本不会被解析器解析 | 4 | CDATA_SECTION_NODE |
| EntityReference | 表示实体引用元素 | 5 | ENTITY_REFERENCE_NODE |
| Entity | 表示实体 | 6 | ENTITY_NODE |
| ProcessingInstruction | 表示处理指令 | 7 | PROCESSING_INSTRUCTION_NODE |
| Comment | 表示注释 | 8 | COMMENT_NODE |
| Document | 表示整个文档,DOM树的根节点 | 9 | DOCUMENT_NODE |
| DocumentType | 为文档定义的实体提供接口 | 10 | DOCUMENT_TYPE_NODE |
| DocumentFragment | 表示文档片段,轻量级的Document对象,仅包含部分文档 | 11 | DOCUMENT_FRAGMENT_NODE |
| Notation | 表示在DTD中声明的符号 | 12 | NOTATION_NODE |
节点名称nodeName和节点值nodeValue
| 节点类型 | 说明 | nodeName返回值 | nodeValue返回值 |
| Element | 表示元素 | 元素的名称(标签的名称) | null |
| Attr | 表示属性 | 属性的名称 | 属性的值 |
| Text | 表示元素或属性中的文本内容 | #text | 节点的内容 |
| CDATASection | 表示文档中的CDATA区段,其包含的文本不会被解析器解析 | #cdata-section | 节点的内容 |
| EntityReference | 表示实体引用元素 | 实体引用名称 | null |
| Entity | 表示实体 | 实体名称 | null |
| ProcessingInstruction | 表示处理指令 | targer | 节点的内容 |
| Comment | 表示注释 | #comment | 注释的文本 |
| Document | 表示整个文档,DOM树的根节点 | #document | null |
| DocumentType | 为文档定义的实体提供接口 | doctype名称 | null |
| DocumentFragment | 表示文档片段,轻量级的Document对象,仅包含部分文档 | #document-fragment | null |
| Notation | 表示在DTD中声明的符号 | 符号名称 | null |
节点关系
- 在节点数中,最顶端的节点为根节点
- 除根节点外,每个节点都有一个父节点
- 节点可以包含任意数量的子节点
- 没有子节点的节点称为叶子节点
- 同级节点、兄弟节点是指拥有相同父节点的节点
访问节点、获取节点
DOM为节点node定义了一些属性,用于对文档树中每个节点进行遍历。
- ownerDocument:返回当前节点的根元素(document对象)。
document.documentElement也可以返回根节点。 - parentNode:返回当前节点的父节点。
- childNode:返回当前节点的子节点列表。
- firstChild:返回当前节点的第一个子节点。
- lastChild:返回当前节点的最后一个子节点。
- nextSibling:返回当前节点之后相邻的同级节点。
- previousSibling:返回当前节点之前相邻的同级节点。
<ul>
<li>第一列</li>
<li>第二列</li>
<li>第三列</li>
</ul>
<script>
var ul = document.getElementsByTagName("ul")[0];
var lis=ul.childNodes
console.log(lis[0].nodeType);//输出3
</script>
调整节点树
Node类型为所有节点定义了一些方法,用于操作节点,如下:
appendChild():向节点的子节点列表末尾添加新的子节点。cloneNode():复制当前节点。接收一个布尔值参数,当为true时复制原节点及所有子节点。当为false时仅复制节点本身。hasChildNodes():判断当前节点是否拥有子节点。insertBefore():在指定的子节点前面插入新的子节点。normalize():合并相邻的Text节点并删除空的Text节点。removeChild():移除(并返回)当前节点的指定子节点。replaceChild():用新节点替换一个子节点。
使用文档节点document
- Document类型表示文档节点,HTMLDocument是Document的子类。
- document对象是HTMLDocument的实例对象。
- document对象是window对象的属性,因此可在全局作用域下直接访问document对象。
//以下两种方式都可以获取document文档节点对象
var a=window.document;
var b=document;访问文档子节点
//可通过以下方式获取文档子节点
var html=document.documentElement;
var html=document.childNodes[0];
var html=document.firstChild;
//通过以下方式直接获取head子节点
var body=document.head;
//通过以下方式直接获取body子节点
var body=document.body;
document属性
文档节点对象拥有很多属性,可以用来获取文档信息,常用的如下:
- title:获取
<title>标签包含的文本信息。 - lastModified:返回文档最后被修改的日期和时间。
- URL:返回当前文档的完整URL,即地址栏中显示的地址信息。
- domain:返回当前文档的域名。
- referrer:返回链接到当前页面的那个页面的URL。当没有源网页时,该属性为空字符串。
document方法
document对象包含多个访问文档内元素的方法,常用的如下:
- getElementById():返回指定id属性值的元素。如果有多个id相同的元素,则返回第一个。如果没有找到,则返回null。
- getElementsByTagName():返回所有指定标签名称的元素节点。
- getElementsByName():返回所有指定name属性值的元素节点。
getElementsByClassName():接收一个字符串参数,包含一个或多个类名,类名通过空格分隔开,返回所有指定class属性值的元素节点。querySelector():接收一个字符串参数,为CSS选择器,返回一个元素对象。querySelectorAll():接收一个字符串参数,为CSS选择器,返回一个元素集合。
需要注意的时,getElementsByTagName()、getElementsByName()、getElementsByClassName()返回的是一个HTMLCollection对象,而不是数组。HTMLCollection对象与nodeList对象类型,可以通过方括号或item()方法访问对象中的元素,并通过length属性取得这个对象元素的数量。
//使用参数*可以获取到所有元素
var allElements=document.getElementsByTagName("*");HTML5下的HTMLDocument
HTML5为HTMLDocument添加了几个实用的属性,如下:
- readyState:表示文档的加载状态,有两值:
- loading:表示正在加载文档。
- complete:表示已经加载完文档。
- compatMode:返回文档的渲染模式。标准模式为CSS1Compat、怪异模式为BackCompay
- head:返回文档的head节点
- charset:返回文档实际使用的字符集。可以动态修改该属性以更改网页的字符编码。
- defaultCharset:返回浏览器默认使用的字符编码,这是一个只读属性,无法修改它
使用元素节点Element
元素节点的特征如下:
- nodeType值为1。
- nodeName返回的元素的标签名称,也可以使用tagName属性获取。
- nodeValue返回null。
- parentNode是Document或Element类型节点。
- 其子节点可以是Element、Text、Comment、ProcessingInstruction、CDATASection或EntityReference。
常用方法:
document.getElementById("id"):通过id准确获取文档中的指定元素,如有多个,返回第一个。document.getElementsByTagName("tagName"):获取指定标签名称的所有元素。note.parentNode():返回节点的父节点。note.nextSibling():返回同级的下一个节点。note.previousSibling():返回同级的上一个节点。note.firstChild():返回第一个子节点。note.lastChild():返回最后一个子节点。document.createElement("tagName"):根据给定的标签名称创建一个新的元素,并返回新建元素的引用。
var p=document.createElement("p");//创建段落元素note.cloneNode():创建一个当前节点的副本
var p=document.createElement("p");
var p1=p.cloneNode(false);//复制节点,false表示不复制节点的子节点。需要注意的是,复制节点方法会把原节点包含的id属性一同复制到新节点。一般情况下,一个文档中,不同元素的id属性值应该不同,因此应修改其中某个节点的id属性值。
note.appendChild(newChild):向当前的子节点列表末尾添加新的子节点,并返回新增的节点。
var p=document.createElement("p");
var txt=document.createTextNode("这是文本节点");
p.appendChild(txt);//把文本节点添加到段落节点中note.insertBefore(newchild,refchild):在已有的子节点前插入一个新的子节点。newchild表示插入新的节点,refchild表示在此节点前插入新节点,返回新的子节点。note.removeChild(note):从子节点列表中删除某个节点。如删除成功,则返回被删除的节点。如删除失败,则返回null。删除时,会把包含的所有子节点同时删除。note.replaceChild(newNode,oldNode):将某个子节点替换为另一个。如果替换成功,则返回被替换的节点。如果替换失败,则返回null。替换节点会把元素的所有子节点也一同替换掉。document.activeElement:该属性可以引用DOM中当前获得了焦点的元素,元素获取焦点的方式包括:页面加载、用户输入(如Tab键)和在脚本调用focus()方法时。
当文档刚加载完成时,document.activeElement引用的时document.body元素。文档加载期间,document.activeElement的值为null。
node.contains(childNode):用来检测某个节点是不是另一个节点的后代。如果是,则返回true。如果不是,则返回false。
使用文本节点Text
文本节点的特征如下:
- nodeType值为3。
- nodeName值为
#text。 - nodeValue值为节点所包含的文本。或使用data属性获取。或通过元素的innerHTML属性获取。
- parentNode是一个Element类型节点。
- 不包含子节点。
常用方法如下:
nodeValue、data、length:获取Text节点包含的文本及文本长度。document.createTextNode(data):创建文本节点,data为文本内容。node.appendData(string):将字符串string追加到文本节点的尾部。deleteData(start,lenght):从start下标位置开始删除lenght个字符。insertData(start,string):从start下标位置插入字符串string。replaceData(start,length,string):使用字符串string替换从start下标位置开始length个字符。splitText(offset):在offset下标位置把一个Text节点分割成两个节点。substringData(start,length):从start下标位置开始提取length个字符。
插入HTML字符串
innerHTML属性
元素的innerHTML属性可以返回元素内部的HTML字符串。也可以该属性赋值,根据传入的HTML字符串,创建新的DOM片段,然后用这个DOM片段完全替换调用元素内原有的所有子节点。
需要注意的是innerHTML插入
<script>标记后,并不会执行其中的脚本。

insertAdjacentHTML方法
insertAdjacenetHTML(pos,html)方法是另一种插入HTML字符串的方式。
它接收两个参数,第一个参数设置插入的位置,第二个参数设置插入的HTML字符串。
第一个参数必须为以下列值之一:
- beforebegin:在当前元素之前插入一个紧邻的同辈元素。
- aferbegin:在当前元素之下插入一个新的子元素,或在第一个子元素之前再插入一个新的子元素。
- beforeend:在当前元素之下插入一个新的子元素,或在最后一个子元素之后再插入一个新的子元素。
- afterend:在当前元素之后插入一个紧邻的同辈元素。
以上参数中,begin代表元素的开始标签,end代表元素的结束标签。before代表前,end代表后。
outerHTML属性
outerHTML属性与innerHTML功能类似,但它返回的是调用它的元素本身及所有子节点的HTML标签。对该属性赋值,会完全替换被调用元素。 
插入文本
元素的innerText和outerText属性,用于获取元素的文本内容。
- 当为读模式时,innerText、outerText返回元素内部的所有文本内容。
- 当为写模式时,innerText会替换指定元素内的文本内容。outerText会覆盖掉原有的元素。写模式下,HTML字符串会被编码显示,而不是创建DOM树。
文档片段节点DocumentFragment
文档片段节点DocumentFragment在文档树中没有对应的标记,不会在页面上显示,DOM允许用户通过javascript操作文档片段节点。
因为在文档片段不会被添加到DOM树中,因此可以避免浏览器渲染和占用资源。对于大段的DOM树修改,一般是在文档片段节点中完成后,再一次性添加到文档树中。
元素的appendChild()和insertBefore()允许添加文档片段节点到文档树中。
var fragment=document.createDocumentFragment();//创建一个文档片段节点
var p=document.createElement("p");//创建一个段落元素节点
p.innerText="添加的文本";//为段落元素节点添加文本内容
fragment.appendChild(p);//将段落元素节点添加到文档片段节点
document.getElementById("div").appendChild(fragment);//将文档片段节点添加到DOM树,使其在页面上显示DocumentFragment具有以下特征:
- nodeType值为11
- nodeName值为
#document-fragment - nodeValue值为null
- parentValue值为null
- 子节点可以是Element、ProcessingInstruction、Comment、Text、CDATASection或EntityReference。
属性节点Attr
属性节点Attr存储了文档树中元素的属性,具有以下特征:
- nodeType值为11
- nodeName值是属性的名称
- nodeValue值是属性的值
- parentNode值为null
- 在HTML中不包含子节点,在XML中子节点为Text、EntityReference
属性节点还有3个专用属性:
- name:返回属性的名称,等用于nodeName
- value:返回属性的值,等同于nodeValue
- specified:如果属性值是在代码中设置的,则返回true。如果为默认值,则返回false。
获取属性值
属性节点并不被认为是DOM树中的一部分,因此没有提供直接访问的方法。一般通过以下方法获取属性节点或属性值:
element.getAttributeNode("attr-name"):返回属性节点element.attribute["attr-name"]:返回属性节点element.getArrtibute("attr-name"):返回属性的属性值,如属性不存在,则返回null。
一般不建议使用数组下标的形式去获取属性节点,因为不同浏览器对其支持不一样。
在传统DOM中,常用点语法去获取元素的属性,如下面的例子:
var img=document.getElementById("img");//获取id为img的标签
var src=img.src;//获取img元素的src属性点语法优点是方便,缺点是不是所有的属性都被Javascript映射,不一定能直接获取到属性值,因此更推荐使用标准的写法去获取。
还需要注意的是,因为某些属性名在javascript中是保留字,所以用点语法时需要使用修改过的属性名,如:
- class属性,使用className属性名获取
- for属性,使用htmlFor属性名获取
- css中的float属性,使用cssFloat属性名获取
- css中的text属性,使用cssText属性名获取
设置属性值
使用element.setAttribute(name,value)设置元素的属性值,或者是用点语法的方式设置属性值。
删除属性值
使用element.removeAttribute(name)删除元素的属性
添加自定义属性
在HTML5中允许我们自定义元素的属性,自定义的属性的属性名要以data-开头,如:
<div id="box" data-myid="myid" data-mypass="pass">自定义属性</div>添加自定义属性后,可以通过元素的dataset属性访问自定义属性,dataset属性的值是一个DOMStringMap实列,是一个键值对映射,通过以下方式获取属性值。
var div=document.getElementById("box");
console.log(div.dataset.myid);//输出myid
console.log(div.dataset.mypass);//输出mypass由于dataset属性在各个浏览器的支持不一样,因此还是推荐使用
getAttribute()方法获取属性值。
动态添加Javascript脚本的方式
动态添加Javascript脚本的方式有两种,分别是插入外部文件和直接插入Javascript代码。
插入外部文件
- 通过
var script=document.createElement('script')创建script元素节点。 - 给script元素节点的src属性赋值javascript脚本url地址。
- 通过
document.body.appendChild(script)将script元素节点添加到页面。
当script元素节点添加到页面后,将会自动下载外部文件。
直接插入Javascript代码
- 通过
var script=document.createElement('script')创建script元素节点。 - 通过
var js=document.createTextNode("function say(){alert('h1');}")创建包含js代码的文本节点。 - 通过
script.appendChild(js)将文本节点添加到script元素节点中。 - 通过
document.body.appendChild(script)将script元素节点添加到页面。
eval()函数
eval函数在JavaScript中是一种非常强大的工具,但也带有很高的风险。它的主要作用是将传递给它的字符串作为JavaScript代码执行。具体来说,eval函数会将一个字符串解析为JavaScript代码并执行该代码。
var result=eavl('2+2');
console.log(result);//输出4Javascript的事件处理
基本概念
事件模型:
- 基本事件模型:DOM0事件模型,浏览器初期出现的一种比较简单的事件模型,主要通过元素的事件属性绑定事件处理函数。各大浏览器都支持,但比较依赖于HTML文档标签,不利于Javascript开发。
- DOM事件模型:由W3C制定,是目前标准的事件处理模型。
- IE事件模型:IE4.0及其以上版本浏览器支持,与DOM事件模型类似,用法不同。
- Netscape事件模型:由Netscape浏览器实现,Netscape6中已停止支持。
事件流:多个节点对象对同一种事件进行响应的先后顺序。其有以下类型:
- 冒泡型:事件从最特定的目标向最不特定目标(document)触发,也就是事件从下向上进行响应,这个传递过程被形象地称为冒泡。
- 捕获型:事件从最不特定的目标(document对象)开始触发,然后到最特定的目标,也就是事件从上向下进行响应。
- 混合型:W3C的DOM事件模型支持捕获新和冒泡型两种事件流。先发生捕获型事件流然后才发生冒泡型事件流,两种事件流会触及DOM中的所有层级对象,从document对象开始最后返回到document对象。
根据事件流类型,可以把事件传播分为3个阶段:
- 捕获阶段:事件从document对象沿着对象树向下传递,事件会首先被注册了相同事件的上级节点捕获并执行,再依次向下传播。从上往下。
- 目标阶段:注册在目标节点上的事件被执行。
- 冒泡阶段:事件从目标节点沿着对象树向上传递,如果上级节点注册了相同的事件,将会逐级响应,依次向上传播。从下往上。
绑定事件
在基本事件模型中绑定事件的方式有两种:
- 静态绑定:把Javascript脚本作为属性值,直接赋值给事件属性。
<button onclick="alert('点击了按钮')">点击</button>- 动态绑定:使用DOM对象的事件属性进行赋值。
<button>点击</button>
<script>
var btn = document.getElementsByTagName("button")[0];
btn.onclick = function () {
alert("点击了按钮");
}
</script>事件处理函数不需要参数,默认包含了event参数对象,event对象包含了事件信息,在函数内进行传播。
<button>点击</button>
<script>
var btn = document.getElementsByTagName("button")[0];
btn.onclick = function (e) {
console.log(event);
console.log(e);
}
</script>注册事件
DOM事件模型注册事件
在DOM事件模型中,通过调用对象的addEventListener()方法注册事件,用法如下:
element.addEventListener(String type,Function listener,boolean useCapture)- type:注册事件的类型名。事件类型名和事件属性名不同,事件类型名没有on前缀。如事件类型名
click,事件属性名onclick。 - listener:监听函数,即事件处理函数。在指定类型的事件发生时将会执行该函数。默认传递唯一参数event对象。
- useCapture:一个布尔值。默认值为false。为true时,事件处理函数在事件传播的捕获阶段被执行。为false时,事件处理函数在事件传播的冒泡阶段被执行。
//以下代码,当点击按钮时,会先执行b函数,然后执行a函数。
<button id="btn" onclick="a()">点击</button>
<script>
var btn=document.getElementById("btn");
btn.addEventListener("click",b,true);
function a(){
alert("我是a函数")
}
function b(){
alert("我是b函数")
}
</script>早期的IE浏览器不支持addEventListener()方法,直到IE8才开始支持DOM事件模型。
IE事件模型注册事件
IE事件模型使用attachEvent()方法注册事件,用法如下:
element.attachEvent(etype,eventName);- etype:设置事件类型,如onclick、onkeyup、onmousemove等
- eventName:设置事件名称,也就是事件处理函数。 使用attachEvent()注册事件后,其事件处理函数的调用者为window对象,即this指针指向的是window对象。如果要获取当前元素对象,可以使用event对象的srcElement。
需要注意的是:
- 在IE事件模型中,etype为事件类型,需要带on前缀。
- 该方法仅在支持IE事件模型的浏览器中生效,如IE浏览器。
销毁事件
DOM事件模型销毁事件
在DOM事件模型中,使用removeEventListener()方法绑定在对象上的事件监听处理函数移除,其用法如下:
element.removeEventListener(String type,Function listener,boolean useCapture);removeEventListener只能销毁使用addEventListener注册的事件处理函数,并且需要3个参数都一致才能销毁,不能销毁通过事件属性(如onclick属性)绑定的处理函数。
<button id="btn">点我</button>
<button id="remove">取消点击</button>
<script>
var btn = document.getElementById('btn');
btn.addEventListener('click', ok, true);
var remove = document.getElementById('remove');
remove.addEventListener('click', function () {
btn.removeEventListener('click', ok, false)
})
function ok(){
alert('点击了');
}
</script>IE事件模型销毁事件
IE事件模型使用detachEvent()注销事件,用法如下:
element.detachEvent(etype,eventName);event对象的使用
DOM事件模型
DOM事件模型的event对象属性
DOM事件模型中的event对象属性均为只读。
| 属性 | 说明 |
|---|---|
| bubbles | 布尔值,指示事件是否为冒泡事件类型 |
| cancelable | 布尔值,指示事件是否可以取消默认动作 |
| currentTarget | 返回触发事件的当前节点,即当前处理该事件的元素、文档、窗口。 |
| eventPhase | 返回事件的当前传播阶段,捕获阶段(1)、目标事件阶段(2)、冒泡阶段(3) |
| target | 返回事件的目标节点(触发该事件的节点)。如生成事件的元素、文档或窗口 |
| timeStamp | 返回事件生成的日期和时间 |
| type | 返回当前event对象表示的时间的名称。如“summit”、“load”、“click” |
DOM事件模型中。event的target属性和currentTarger属性有什么区别?
- event.target:
- 指向事件发生的源元素,即触发事件的具体元素。
- 即使事件冒泡或捕获到其他元素,event.target 的值始终保持不变,指向最初触发事件的元素。
- event.currentTarget:
- 指向当前处理事件的元素,即事件正在被处理的元素。
- 当事件冒泡或捕获时,event.currentTarget的值会随着事件传播而改变,指向当前处理事件的元素。
- 在事件处理函数中,this指针与event.currentTarget相当。
DOM事件模型的event对象方法
| 方法 | 说明 |
|---|---|
| initEvent() | 初始化新创建的event对象的属性 |
| preventDefault() | 通知浏览器不要执行与事件关联的默认动作 |
| stopPropagation() | 终止事件的进一步传播 |
IE事件模型
IE事件模型中的event对象属性
| 属性 | 描述 |
|---|---|
| cancelBubble | 当设置为true时,可以阻止事件传播到上级包含对象 |
| fromElement | 对mouseover和mouseout事件,fromElement引用移出鼠标的元素 |
| toElement | 对于mouseover和mouseout事件,该属性引用移入鼠标的元素。 |
| keyCode | 对于keypress事件,为敲击键盘生成Unicode字符。对于keydown和keyup事件,为被敲击的键的虚拟键盘码。 |
| offsetX、offsetY | 发生事件的地点在事件源元素的坐标系统中的X坐标和Y坐标 |
| returnValue | 当设置为false时,取消发生事件的源元素的默认动作。 |
| srcElement | 对于生成事件的window对象、document对象、element对象的引用 |
| x、y | 事件发生的位置的x坐标和y坐标,它们相对于用css定位的最内层包含元素。 |
事件委托
事件委托也称为事件托管或事件代理,是指把目标节点的事件绑定到祖先节点上。这种注册方式是基于事件传播中,逐层冒泡总能被祖先节点元素所捕获。
<ul id="ul">
<li>第1项目</li>
<li>第2项目</li>
<li>第3项目</li>
</ul>
<button id="btn">添加项目</button>
<script>
var ul = document.getElementById('ul');
var btn = document.getElementById('btn');
ul.addEventListener("click", function (e) {
if (e.target.tagName.toLowerCase() === 'li') {
alert(e.target.innerHTML);
}
})
var i = 4;
btn.addEventListener("click", function () {
var li = document.createElement('li');
li.innerHTML = '第' + i + '个项目';
i++;
ul.appendChild(li);
})
</script>
鼠标事件
| 事件类型 | 说明 |
|---|---|
| click | 单机鼠标左键时发生,如果右键也按下则不会发生;当用户的焦点在按钮上,并按了回车时。同样会触发这个事件。 |
| dblclick | 双击鼠标左键时发生,如果右键也按下则不会发生。 |
| mousedown | 单机任意一个鼠标按钮时发生。 |
| mouseup | 松开任意一个鼠标按钮时发生。 |
| mouseover | 鼠标指针移入某个元素时触发 |
| mouseout | 鼠标指针移出某个元素时触发 |
| mousemove | 鼠标在某个元素上时持续发生。 |
mouseover和mouseout事件
- 当鼠标指针移动到某个元素上时,会触发mouseover事件。
- 当鼠标从某个元素上移出时,会触发mouseout事件。
如果从父元素中移动到子元素中时,也会触发父元素的mouseover事件。
<div>
<div>
<div>盒子三
</div>
</div>
</div>
<script>
var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
divs[i].addEventListener('mouseover', function (e) {
this.style.borderColor = "red";
})
divs[i].addEventListener('mouseout', function (e) {
this.style.borderColor = "black";
})
}
</script>
<style>
div {
height: 200px;
width: 50%;
border-width: 1px;
border-style: solid;
}
</style>鼠标定位
| 属性 | 说明 | 兼容性 |
|---|---|---|
| clientX | 以浏览器窗口左上角为原点,定位x轴坐标 | 所有浏览器,不兼容safari |
| clientY | 以浏览器窗口左上角为远点,定位y轴坐标 | 所有浏览器,不兼容safari |
| offsetX | 以当前事件的目标对象左上顶角为原点,定位x轴坐标 | 所有浏览器,不兼容Mozilla |
| offsetY | 以当前事件的目标对象左上顶角为原点,定位y轴坐标 | 所有浏览器,不兼容Mozilla |
| pageX | 以document对象(即文档窗口)左上顶角为原点,定位x轴坐标 | 所有浏览器,不兼容IE |
| pageY | 以document对象(即文档窗口)左上顶角为原点,定位y轴坐标 | 所有浏览器,不兼容IE |
| screenX | 以计算机屏幕左上顶角为原点,定位x轴坐标 | 所有浏览器 |
| screenY | 以计算机屏幕左上顶角为原点,定位y轴坐标 | 所有浏览器 |
| layerX | 以最近的绝对定位的父元素(如果没有,则为document对象)左上顶角为原点,定位x轴坐标 | Mozilla和Safari |
| layerY | 以最近的绝对定位的父元素(如果没有,则为document对象)左上顶角为原点,定位y轴坐标 | Mozilla和Safari |
<div id="box" style="height: 50px;width: 50px;background-color: antiquewhite;"></div>
<script>
function move(o, x, y, event) {
var posX = 0;
var posY = 0;
posX = event.pageX;
posY = event.pageY;
o.style.position = "absolute";
o.style.left = posX - 25 + "px";
o.style.top = posY - 25 + "px";
}
var box=document.getElementById("box");
box.onmousemove=function (event) {
move(this, 50, 50, event);
}
</script>鼠标按键
通过事件对象的button属性可以获取当前鼠标按下的键,该属性可用于click、mousedown、mouseup、dbclick事件类型。
| 按键 | IE事件模型 | DOM事件模型 |
|---|---|---|
| 左键 | 1 | 0 |
| 中键 | 2 | 2 |
| 右键 | 4 | 1 |
| IE事件模型下可以使用掩码技术检测按下的键,比如同时按下左键+右键时,button值为5(1+4)。DOM事件模型不支持。 |
当鼠标单击事件发生时,会触发很多事件,事件响应顺序如下:
mousedown->mouseup->click->mousedown->mouseup->click-dbclick当鼠标在对象间移动时,事件触发顺序如下:
mouseout->mousemove->mouseovier键盘事件
键盘事件类型
键盘事件包括3种:
- keydown:在键盘上按下某个键时持续触发。
- keypress:按下某个键盘键并释放时触发。如果按住某个键不放,会持续触发。
- keyup:释放某个键时触发。该事件在释放按键时触发一次,不会持续触发。
键盘事件属性
| 属性 | IE事件模型 | DOM事件模型 |
|---|---|---|
| keyCode(keypress) | 返回所有字符键的正确键,区分大小写状态 | 功能键返回正确值,shift、ctrl、alt、PrintScreen无返回值,其他返回0 |
| keyCode(keydown、keyup) | 返回所有键值(除PrintScreen),字母键都以大写状态显示键值。 | 返回所有键值(除PrintScreen),字母键都以大写状态显示键值。 |
| charCode(keypress) | 不支持该属性 | 返回字符键,区分大小写,shift、ctrl、alt、PrintScreen无返回值,其他返回0 |
| charCode(keydown、keyup) | 不支持该属性 | 所有键值为0 |
事件触发顺序
- 对于字符键来说,键盘事件的响应顺序如下:
keydown->keypress->keyup- 对于非字符键来说,键盘事件的响应顺序如下:
keydown->keyup页面事件
页面加载load事件
load事件类型在页面完全加载完毕后触发,即在所有的图形图像、外部文件等内容全部加载完毕之前,任何DOM操作都不会发生。
为window对象绑定load事件类型的方法有两种:
- 直接为window对象注册load事件处理函数
window.onload=f;
functon f(){
alert("页面加载完毕")
}- 在页面的
<body>标签中定义onload处理函数。
<body onload=f()></body>
<script>
function f(){
alert("页面加载完毕");
}
</script>注意点:
- 如果同时使用两种方法去注册load事件的处理函数,通过window对象注册的方式优先级会更高,通过window对象注册的load事件方法会覆盖body标签的定义load事件方法。
- 通过属性注册的处理函数,会互相覆盖,最终只会有一个绑定的响应函数被调用。
- 通过addEventListener方法注册事件,可以注册多个处理函数。
页面加载DOMContentLoaded事件
当HTML文档被完全加载和解析,不需要等待样式表、图像和子框架的完成加载,DOMContentLoaded事件就会触发。
DOMContentLoaded事件需要使用document.addEventListener注册
document.addEventListener('DOMContentLoaded', function() {
console.log('DOM fully loaded and parsed');
});页面卸载unload和beforeunload事件
- unload事件:在从当前浏览器窗口内移动文档的位置时触发,即通过超链接、前进、后退按钮等方式从一个页面跳转到其他页面,或关闭浏览器窗口时触发。
- beforeunload事件:该事件与unload事件类型,beforeunload事件的处理函数可以返回一个字符串信息,这个字符串会显示在一个确认对话框中。当用户离开页面时,会弹出这个对话框。
这两个事件在window对象下都有其事件属性。
<div>
<a href="https://www.baidu.com">百度一下</a>
</div>
<script>
window.onunload = function (e) {
console.log("unload式退出");
}
window.onbeforeunload = function (e) {
console.log("beforeunload式退出");
return "beforeunload式退出";
}
</script>
窗口重置resize事件
resize事件类型是在浏览器窗口被重置时触发,如当用户调整窗口大小,或者最大化、最小化、恢复窗口大小时触发resize事件。
resize事件可以通过window对象的onresize属性注册。
<div id="box"></div>
<script>
window.onresize = function (event) {
console.log('resize');
}
</script>页面滚动scroll事件
scroll事件类型用于在浏览器窗口内移动文档的位置时触发,如通过键盘箭头键、翻页键或空格键移动文档位置,或者通过滚动条滚动文档位置。
scroll事件可以通过window对象的onscroll属性注册。
<div style="width: 200%;height: 200%;"></div>
<script>
window.onscroll = function () {
console.log(document.body.scrollLeft + ',' + document.body.scrollTop);
}
</script>错误处理error
error事件类型时在Javascript代码发生错误时触发的,利用该事件可以捕获并处理错误信息。
error事件不传递event事件对象,但传递一个message错误解释对象。
在error事件处理函数中,默认包含5个参数:
- message:表示错误信息。
- source:表示出错文件的URL。
- lineno:表示文件中错误位置的行号。
- colno:表示错误文件中错误位置的列号。
- error:表示错误对象。
error事件返回值为布尔值:
- 当为false时,在浏览器的控制台上会弹出错误提示对话框,显示标准的出错信息。
- 当为true时,在浏览器的控制台上不会显示标准出错信息。
window.onerror = function (message, source, lineno, colno, error) {
console.log('捕获到错误message:', message);
console.log('捕获到错误source:', source);
console.log('捕获到错误lineno:', lineno);
console.log('捕获到错误colno:', colno);
console.log('捕获到错误error:', error);
}
a.log();UI事件
焦点处理:focus(获取焦点)和blur(失去焦点)事件
- focus事件:当点击或使用tab键切换到某个表单元素(input)或超链接(a)上时,会触发该事件。默认状态下,整个文档处于焦点状态下。
- blur事件:在表单元素(input)或超链接(a)失去焦点时,触发该事件。
<input type="text">
<input type="text">
<script>
var inputls = document.getElementsByTagName("input");
for (var i = 0; i < inputls.length; i++) {
inputls[i].onfocus = function () {
this.style.borderWidth = "5px";
}
inputls[i].onblur = function () {
this.style.borderWidth = "3px";
}
}
</script>每个表单元素都有focus()和blur()方法,可以使表单获得焦点或失去焦点。
需要注意的是,隐藏的表单字段通过
focus()使其获取焦点的话,会触发异常。
文本选择:select事件
当用户选中文本框中一个或多个字符时触发select事件,该事件通常用于<input>或<textarea>元素。
同时提供了select()方法,该方法用于选择文本框(input或textarea元素)中的文本。调用select()方法后,文本框中所有文本将被选中。
<textarea id="myTextarea">这是一个文本</textarea>
<div><button id="btn">选中所有</button>
</div>
<p></p>
<script>
var myTextarea = document.getElementById("myTextarea");
var myP = document.getElementsByTagName("p")[0];
myTextarea.onselect = function (event) {
var textarea = event.target;
var text = textarea.value.substring(textarea.selectionStart, textarea.selectionEnd)
console.log(text);
myP.innerText = text;
}
var btn = document.getElementById("btn");
btn.addEventListener("click", function () {
myTextarea.select();
})
</script>字段值变化监测:change事件
change事件类型在表单元素的值发生变化时触发。它主要用于input、select和textarea元素。
- 对于input和textarea元素,当失去焦点且value值发生变化时,触发事件。
- 对于select元素,当value值发生变化时,触发事件。
<input type="text" id="a">
<input type="text" id="b">
<script>
var a = document.getElementById('a');
var b = document.getElementById('b');
a.onchange = function () {
console.log(a.value)
}
a.onkeyup=function(){
b.value=a.value;
}
</script>对input元素和textarea元素绑定change事件时,由于是在失去焦点时才触发事件,因此会感觉到明显的延迟响应现象。这里使用onkeyup事件,可以提供响应的速度。
提交表单:submit事件
使用<input>和<button>标签都可以定义提交按钮,当点击提交按钮,或在文本框中输入文本时按回车键都会触发submit事件。
表单节点调用submit()方法也可以使用提交动作。
<form id="form1" action="#">
<input type="text" name="username" value="">
<input type="submit" value="提交">
</form>
<script>
var form1 = document.getElementById('form1');
form1.onsubmit = function (event) {
var input0 = document.getElementsByTagName('input')[0];
console.log(input0.value);
return false; // 阻止表单提交
}
</script>重置表单:reset事件
为<input>或<button>标签设置type="reset"属性可以定义重置按钮。
<input type="reset" value="重置按钮">
<button type="reset">重置按钮</button>点击重置按钮时,会将所有的输入内容都重置为默认值,同时触发reset事件。
<form action="">
<input type="text" value="默认文本">
<input type="reset" value="重置">
</form>
<script>
var form = document.getElementsByTagName('form')[0];
form.onreset = function () {
alert('重置事件');
}
</script>表单节点调用reset()方法,也可以实现重置表单的功能。
剪贴板事件
HTML5中定义了以下几种剪贴板事件:
- beforecopy:在发生复制操作前触发。
- copy:在发生复制操作时触发。
- beforecut:在发生剪切操作前触发。
- cut:在发生剪切操作时触发。
- beforepaste:在发生粘贴操作起触发。
- paste:在发生粘贴操作时触发。
<p>这是一段文本</p>
<p>这是一段文本</p>
<script>
var p = document.getElementsByTagName('p')[0];
p.addEventListener("beforecut", function () {
console.log("剪切之前");
})
p.addEventListener("cut", function () {
console.log("剪切之后");
})
</script>使用Ajax
Ajax基础
XMLHttpRequest是Javascript一个外挂组建,用来实现客户端与服务端异步通信。
XMLHttpRquest的常用方法:
abort():取消当前的请求getAllReponseHeaders():获取响应的所有HTTP头信息getReponseHeader():从响应信息中获取指定的HTTP头信息open():创建新的HTTP请求,并指定请求方法、URL以及验证信息(用户名、密码)send():发送一个请求setRequestHeader():单独指定请求的某个HTTP头信息
XMLHttpRequest的常用属性:
- onreadystatechange:指定readyState属性改变时的事件处理句柄(处理函数)。
- readyState:返回当前请求的状态。
- responseBody:将回应信息正文以unsigned byte数组形式返回。
- responseStream:将回应信息正文以AOD Stream对象的形式返回
- responseText:以字符串形式返回响应信息
- responseXML:将回应信息以xml对象格式返回
- status:当前请求的http状态码
- statusText:返回当前请求的响应行状态
使用Ajax发送一个请求
使用Ajax发送一个请求需要完成以下步骤:
- 定义XMLHttpRequest对象
- 创建XMLHttpRequest链接
- 发送GET、POST请求
- 获取响应的数据
定义XMLHttpRequest对象
现代标准浏览器都支持XMLHttpRequest对象,创建方式如下:
var xmlHttp=new XMLHttpRequest();IE浏览器则通过ActiveX组件形式创建XMLHttpRequest()对象,创建方式如下:
var xmlHttp=new ActiveObject("Msxml2.XMLHTTP");
//或
var xmlHttp=new ActiveObject("Microsoft.XMLHTTP");创建XMLHttpRequest连接
创建XMLHttpRequest对象后,使用其open()方法建立一个HTTP请求。open()方法用法如下:
xmlHttp.open(method,url,isAsync,user,password);共5个参数,其中前两个参数是必须的。参数说明如下:
- method:请求的方法的字符串值,如:POST、GET,大小写不敏感。
- url:请求的地址的字符串值,可以是绝对路径或相对路径。
- isAsync:布尔值。指定请求是否为异步方式。默认值为true。当为true时,则为异步调用,当调用状态readyState改变时,会调用onreadystatechange指定的回调函数。
- user:如果服务器需要验证身份时,可通过该参数指定用户名。如未指定,浏览器会弹框让用户输入。
- password:如果服务器需要验证身份时,可通过该参数指定密码。如未指定,浏览器会弹框让用户输入。
xmlHttp=new XMLHttpRequest();
xmlHttp.open("GET","www.baidu.com");发送GET、POST请求
创建XMLHttpRequest请求后,使用send()方法,发送请求到服务器,用法如下:
xmlHttp.send(body);参数body为将要发送到服务器的数据,如不需要传递数据,可以将参数设置为null。
使用setRequestHeader()方法设置请求头,用法如下:
xmlHttp.setRequestHeader("Header-name","value");发送GET请求时,通常请求参数都是放在请求参数中,通常参数需要encodeURIComponent()方法进行编码,使其符合URL的格式要求。
encodeURIComponent("asd$%@,.,l,,.")
//'asd%24%25%40%2C.%2Cl%2C%2C.'获取响应数据
XMLHttpRequest对象通过readyState属性表示请求的交互状态,一旦该状态发生变化时,则会触发readyStatechange事件,调用绑定该事件的处理函数。
readyState属性值如下:
- 0:未初始化。表示XMLHttpRequest对象已创建,尚未初始化,即未调用
open()方法。 - 1:初始化。表示已完成初始化,尚未调用
send()方法。 - 2:发送请求。表示请求已发出,即已调用
send()方法,但当前HTTP请求状态及HTTP头未知。 - 3:数据传送中。已经接收部分数据。此时通过responseBody和responseText获取部分数据会出现错误。
- 4:完成。数据接收完毕。此时通过responseBody和responseText可获取完整数据。
在事件处理函数中,通过responseBody、responseText、responseStream、responseXML属性获取响应属性,这些属性都是只读的,不能被修改。
通过两个方法可以获取响应头信息:
getAllResponseHeaders():获取响应的所有HTTP头信息getResponseHeader():从响应信息中获取指定的HTTP头信息。
<button onclick="btnClick('https://www.baidu.com')">点我发送请求</button>
<script>
//这里会有跨域问题
function btnClick(url) {
const xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", url, true);
xmlHttp.send();
xmlHttp.onreadystatechange = function () {
console.log("responseHeaders:" + xmlHttp.getAllResponseHeaders());
console.log("readyState: " + xmlHttp.readyState);
console.log("status: " + xmlHttp.status);
console.log("responseText: " + xmlHttp.responseText);
// if (xmlHttp.readyState == 4) {
// if (xmlHttp.status == 200) {
// console.log(xmlHttp.responseText);
// }
// }
}
}
</script>中止请求
XMLHttpRequest对象提供了abort()方法用于中止正在进行的异步请求。一般在中止异步请求前,我们需要清空onreadystatechange属性绑定的处理函数。
xmlHttp.onreadystatechange=function(){};
xmlHttp.abort();模块化
Javascript提供了模块化特性,通过在<script>中指定type属性的值为module以声明为模块化JavaScript。
JavaScript的模块特性与普通模式相比,有以下几个主要区别和特性:
作用域隔离:
- 模块:每个模块都有自己的作用域,模块中的变量和函数不会污染全局作用域。
- 普通模式:所有脚本共享全局作用域,容易发生命名冲突。
导入和导出:
- 模块:可以使用
import和export语句在模块之间导入和导出变量、函数、类等。模块使代码分离和重用变得更加容易。 - 普通模式:没有直接的机制来导入和导出变量和函数,通常通过全局变量或其他方式共享。
- 模块:可以使用
延迟加载:
- 模块:模块脚本是延迟执行的,类似于添加了
defer属性的普通脚本。它们会在HTML解析完成后按照它们在文档中的顺序执行。 - 普通模式:默认情况下,脚本会立即执行,并阻塞HTML的解析,直到脚本执行完成。
- 模块:模块脚本是延迟执行的,类似于添加了
严格模式:
- 模块:默认启用严格模式,无需显式声明
"use strict";。这会带来更严格的语法和错误检查。 - 普通模式:严格模式需要显式声明,不启用严格模式时,一些语法和行为的检查较为宽松。
- 模块:默认启用严格模式,无需显式声明
顶层
await:- 模块:可以在模块顶层使用
await,使异步代码更简单和直观。 - 普通模式:顶层不支持
await,只能在异步函数中使用。
- 模块:可以在模块顶层使用
文件类型:
- 模块:模块文件通常有一个独立的文件,并且通过
type="module"引入。 - 普通模式:普通脚本可以嵌入在HTML文件中,也可以是单独的文件。
- 模块:模块文件通常有一个独立的文件,并且通过
示例代码:
//function.js
function add(a,b){
return a+b;
}
export default {add};<div>
<button onclick="btnClick">点我</button>
</div>
<script type="module">
import func from "./function.js";
import { add } from "./function.js";
import { add as a } from "./ function.js";
function btnClick() {
var result1 = func.add(1, 1);
console.log(result1);
var result2 = add(1, 1);
console.log(result2);
var result3 = a(1, 1);
console.log(result3);
}
</script>使用模块特性,可以更好地组织代码,提高可维护性和重用性。
Promise语法
Promise是在Javascript中用于处理异步操作一个对象。它代表一个尚未完成但将来可能会完成的操作,并且在操作完成后可以返回处理成功的结果或失败的原因。
通常使用new Promise调用构造函数的方式创建一个Promise对象。向构造函数传递一个execute函数。
execute函数接受两个参数,resolve和reject,它们都是方法的引用。
- resolve:用于包装操作处理成功的结果,参数接收操作成功时返回的数据。
- reject:用于包装操作处理失败的结果,参数一般接收error对象。
在execute函数中通常需要完成异步操作,并在异步操作完成后,使用resolve方法包装处理结果。如果异步操作发生了异常,则使用reject方法包装异常信息。
Promise函数通常是指创建并返回一个Promise对象的函数,这类函数封装了异步操作,并返回一个Promise对象,以便调用这完成链式调用来处理异步操作的结果或错误。
以下示例演示了如何创建一个Promse函数:
function request() {
return new Promise((resolve, reject) => {
try {
console.log('开始执行异步操作');
setTimeout(() => {
resolve("异步操作完成");
}, 2000);
console.log("等待异步操作完成");
} catch (error) {
reject(error);
}
}
);
};当调用Promise构建函数时,整个操作是同步的,会立刻返回一个Promise的对象。只有setTimeout部分是异步的。
以下示例演示了如何调用Promise函数:
function btnClick() {
request().then(data => {
console.log(data);
}).catch(error => {
console.log(error);
}).finally(() => {
console.log("最终:点击了按钮1");
})
console.log("点击了按钮1");
}输出结果 当调用链式操作函数then、catch、finally时,其实际是异步的,它们会被放入事件队列中,在当前事件循环结束后执行。
使用async/await方式调用Promise函数:
async function btnClickAsync() {
try {
let data = await request();
console.log(data);
} catch (error) {
console.log(error);
} finally {
console.log("最终:点击了按钮2");
}
console.log("点击了按钮2");
} 使用await调用Promise函数时,下方的代码也会共同进入到异步等待状态,当Promise函数返回处理结果、事件循环结束后继续执行下方代码。
Promise的高级用法
多个异步操作并行执行
Promise.all()方法可以并行执行多个异步操作,并在所有操作完成后执行回调。
Promise.all([promise1, promise2, promise3])
.then(results => {
// 所有操作都成功
})
.catch(error => {
// 至少有一个操作失败
});- 当所有Promise执行成功时,
Promise.all()会返回一个新的Promise,该Promise的resolve值是由所有Promise的resolve值组成的数组。 - 如果任意其中一个Promise失败,则Promise.all也会失败,并返回第一个失败的Promise的错误信息。
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = function () {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('foo'), 2000);
});
};
function btnClick() {
Promise.all([promise1, promise2, promise3()]).then((results) => {
results.forEach(element => {
console.log(element);//3 42 foo
});
});
}多个异步操作并行执行
Promise.race()方法会在第一个异步操作完成后立即执行回调,无论成功还是失败。
Promise.race([promise1, promise2, promise3])
.then(result => {
// 第一个完成的操作的结果
})
.catch(error => {
// 第一个失败的操作的错误
});以下示例模拟3个异步操作竞争执行:
const promise = function (timeout) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve("延迟为:"+timeout + "的promise执行完毕"), timeout);
});
};
function btnClick() {
Promise.race([promise(1000), promise(999), promise(1001)]).then((result) => {
console.log(result); //延迟为:999的promise执行完毕
});
}顺序执行多个异步操作
可以通过链式调用Promise来顺序执行多个异步操作,每个操作依赖于前一个操作的结果。
promise1
.then(result1 => {
return promise2(result1);
})
.then(result2 => {
return promise3(result2);
})
.then(result3 => {
// 处理最终结果
})
.catch(error => {
// 处理错误
});以下示例模拟链式调用:
const promise = function (timeout) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve("延迟为:" + timeout + "的promise执行完毕"), timeout);
});
};
function btnClick() {
promise(100).then((res) => {
console.log(res);
return promise(200);
}).then((res) => {
console.log(res);
return promise(300);
}).then(res => {
console.log(res);
return promise(400);
}).then(res => {
console.log(res);
});
}对象与JSON字符串的转换
对象转JSON字符串
在javascript中,使用JSON.stringify(obj),将对象转换为JSON字符串。
在JSON.stringify()转换过程中,会忽略掉对象中的函数和值为undefined的属性。日期对象会被转换为ISO字符串。
function objectToJson() {
let obj = {
'id': 1,
'name': '张三',
'age': 18,
'birthday': new Date('1949-10-01'),
'sex': undefined,
'jump': function () {
console.log(name + " jump");
}
}
console.log(obj);
console.log(JSON.stringify(obj))
{"id":1,"name":"张三","age":18,"birthday":"1949-10-01T00:00:00.000Z"}
}json字符串转对象
使用JSON.parse(str)方法,将JSON字符串转换为对象。
function jsonToObject() {
let json = '{"id":1,"name":"张三","age":18,"birthday":"1949-10-01T00:00:00.000Z"}';
let obj = JSON.parse(json);
console.log(obj);
//{id: 1, name: '张三', age: 18, birthday: '1949-10-01T00:00:00.000Z'}
}解构赋值
在JavaScript中,解构赋值(Destructuring Assignment)是一种从数组或对象中提取数据并将其分配给变量的语法。对于对象的解构赋值,可以从对象中提取多个属性,并将它们赋值给相应的变量。
let myObj={
id:1,
name:'zhangsan'
}
let {id,name}=myObj;//从myObj对象中获取id和name属性,赋值到名为id、name的变量上。扩展运算符或剩余参数...
在javascript中,...根据上下文不同,可以有拓展运算符和剩余参数两种使用用途。
- 扩展运算符:扩展运算符用于在数组或对象中展开元素。
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5, 6];
console.log(arr2); // 输出: [1, 2, 3, 4, 5, 6]
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 };
console.log(obj2); // 输出: { a: 1, b: 2, c: 3 }- 剩余参数:剩余参数用于函数参数中,收集所有未单独列出的参数,形成一个数组。
function myFunction(a, b, ...rest) {
console.log(a); // 输出: 1
console.log(b); // 输出: 2
console.log(rest); // 输出: [3, 4, 5]
}
myFunction(1, 2, 3, 4, 5);模板字符串
模板字符串(Template Literals)是ES6引入的一种新的字符串表示方法,允许在字符串中嵌入表达式。它们使用反引号(`)而不是普通的单引号(')或双引号(")。模板字符串提供了更强大的字符串操作功能,包括:
- 内嵌表达式: 可以在模板字符串中嵌入表达式,用
${表达式}的形式。javascriptconst name = 'Alice'; const age = 25; console.log(`My name is ${name} and I am ${age} years old.`); // 输出:My name is Alice and I am 25 years old. - 多行字符串: 可以直接在模板字符串中写多行文本,而不需要使用换行符。javascript
const message = `Hello, This is a multi-line string. Nice to meet you!`; console.log(message); // 输出: // Hello, // This is a multi-line string. // Nice to meet you! - 嵌入变量和表达式: 可以在模板字符串中嵌入任意的JavaScript表达式。javascript
const a = 5; const b = 10; console.log(`The sum of ${a} and ${b} is ${a + b}.`); // 输出:The sum of 5 and 10 is 15. - 嵌套模板字符串: 可以在模板字符串中嵌套其他模板字符串。javascript
const nested = `This is ${`a nested`} template string.`; console.log(nested); // 输出:This is a nested template string.
lodash
Lodash 是一个 JavaScript 的实用工具库,提供了很多常用的函数,用于简化编写 JavaScript 代码的过程。它提供了一些优化性能和功能强大的函数,可以处理数组、对象、函数等各种数据。Lodash 的设计目标是提高开发效率,同时保持代码的可读性和可维护性。
//CDN方式引入
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
//按需导入
npm install lodash-es
import { map, filter } from 'lodash-es';Radash
Radash 是一个用于 JavaScript 和 TypeScript 的实用程序库,旨在简化常见的编程任务。它类似于 Lodash 或 Ramda 等库,但可能具有自己的特定功能和设计理念。Radash 提供了一组函数,可以帮助开发者处理数组、对象、字符串等数据类型,从而提高代码的可读性和可维护性。开发者可以使用 Radash 来进行数据转换、查找和处理等操作,使开发过程更加高效和便捷。
//按需导入
npm install radash
import { compact } from 'radash';提供了以下这些功能模块:
- 数组操作
- 对象操作
- 字符串操作
- 函数操作
- 数学操作
- 时间操作