JavaScript基础学习笔记
前言
本学习笔记为我个人结合b站的尚硅谷JavaScript基础课程自学总结而来,记录学习成果,交流学习经验,希望能对广大Web前端学习者有所帮助。学习JavaScript基础,需要具备HTML和CSS基础,可以查看本人的HTML和CSS学习笔记,内有课程视频链接。JavaScript基础课程学习结束后,接JavaScript高级课程,可以查看本人的JavaScript高级学习笔记,如未更新,敬请期待。本人能力有限,学识尚浅,如有谬误,欢迎交流。感谢各位的阅读、评论,如有引用、转发需要征得本人同意,保留权利。
1 JavaScript
1.1简介
1. JavaScript起源于1995年,最初用于处理网页前端验证,Netscape网景公司,ECMAScript标准,面向对象。
ECMAScript
2. JavaScript构成 DOM
BOM
1.2基本语法
1. 路径:文件所在位置
2. 目录:文件所在文件夹
3. 引号嵌套:双引号中使用单引号,编程中必须使用直引号,英文书写中建议使用弯引号
4. 单行注释://注释内容
5. 多行注释:/*注释内容*/
6. JavaScript代码位置:
(1) <script></script>标签中
弹出带有确定按钮的警告框alert(“内容”);
向body标签中输出document.write(“内容”);
向控制台中输出console.log(“内容”); //三种语句顺序执行
(2) HTML代码的属性中
button onclick=”alert(‘点击按钮后,弹出警告框,显示的内容’);”></button>
<a href=”javascript:alert(‘点击超链接后,弹出警告框,显示的内容‘);”></a>
(3) 单独的.js文件中,通过<script src=”.js文件路径”></script>引用
JavaScript文件扩展名.js
script标签用于引用外部.js文件后,就不能用于写入内部JavaScript代码,如果需要,另起一个script标签
7. var 标识符; //声明变量
标识符 = 值; //变量赋值
var 标识符 = 值; //声明变量并赋值
标识符不能以数字开头,可以包括字母、数字、下划线和$,不能与关键字相同,驼峰命名法
JavaScript底层采用Unicode万国码保存标识符,理论上可以使用汉字等字符
8. 转义字符:
转义符\
换行\n //仅用于JavaScript中,向HTML页面中输出时,换行还用HTML标签和实体转义字符
制表符\t
Unicode编码转义符\u四位十六进制Unicode编码
1.3 数据类型
1. 数据类型:
|
字符串 |
String |
用引号括起 |
|
数值 |
Number |
包括整数和浮点数,最大值Number.MAX_VALUE,无穷大Infinity,加负号表示最小值和无穷小,NaN=Not a Number非数值,最大精度Numer.MIN_VALUE=0以上最小值,最小的小数 |
|
布尔型 |
Boolean |
|
|
未定义 |
Undefined |
声明变量但未赋值 |
|
空值 |
Null |
Object对象数据类型中的一个值 |
|
对象 |
Object |
|
typeof 标识符; //返回指定数据的数据类型的字符串表达形式的运算符
2. 数据类型转换:
转换为String:
(1) 调用String toString()方法,返回String类型,Null和Undefined没有toString()方法
(2) String String()函数,以被转换数据作为参数,返回String类型,可以转换Null和Undefined
(3) 隐式类型转换:任何数据类型 + “”,返回String类型
转换为Number:
(1) number Number()函数,以被转换数据作为参数,返回Number类型
纯数字String→Number
含有字符String→NaN
空String/空格String→0
true→1
false→0
Null→0
Undefined→NaN
(2) number parseInt()函数,获取String中,从第一位起的有效整数,转换为Number类型并返回,可用于取整
(3) number parseFloat()函数,获取String中,从第一位起的有效小数,转换为Number类型并返回
非String类型会先转换为String类型
(4) 隐式类型转换:+任何数据类型,返回Number类型
转换为Boolean:
(1) boolean Boolean()函数:Number 0,Number NaN,String ””,Null,Undefined→false,其他均为true
(2) 隐式类型转换:!!任何数据类型,返回Boolean类型
3. 数字进制转换:其他进制的数字会自动转换成十进制显示
|
二进制 |
0b开头 |
浏览器兼容不佳 |
|
八进制 |
0开头 |
0开头数字String有时会被转换成八进制,有时会被装换成十进制 parseInt(a,10) //将String a转换成十进制数 |
|
十进制 |
|
|
|
十六进制 |
0x |
|
1.4 运算符
1. NaN与任何数据进行运算均为NaN
2. 与&&运算和或||运算是短路逻辑,首先判断第一个操作数,如果能得出结果,则返回第一个操作数,如果不能,再判断第二个操作数,此时返回第二个操作数
3. 比较运算符将非Number转换为Number比较,将String转换为Unicode码值逐字符比较,如果需要比较两个String类型数字,需要类型转换
4. 相等==运算和不相等!=运算将非Number转换为Number比较,严格等于===和不严格等于!==会比较数据类型
5. 判断数据是否为NaN,可以使用boolean isNaN()函数,也可以使用严格等于===
6. 在JavaScript代码中使用Unicode编码:转义字符\u四位十六进制Unicode编码
7. 在HTML代码中使用Unicode编码:&#十进制Unicode编码;
|
数据类型 运算符 |
ytpeof 标识符; |
与 |
&& |
|
字符串拼接运算符 |
String + 任何数据类型 |
或 |
|| |
|
加法 运算符 |
非String + 非String |
非 |
! |
|
减法 运算符 |
任何数据类型 – 任何数据类型 |
赋值 运算符 |
= |
|
乘法 运算符 |
任何数据类型 * 任何数据类型 |
拓展 赋值 运算符 |
+=、-=、*=、/=、%= |
|
除法 运算符 |
任何数据类型 / 任何数据类型 |
相等 运算符 |
==、!=、===、!== |
|
取余 运算符 |
% |
比较 运算符 |
>、<、>=、<= |
|
自增 运算符 |
i++和++i(前置运算符效率更高) |
三元 运算符 |
条件表达式 ? 语句1 : 语句2; |
|
自减 运算符 |
I--和--i(前置运算符效率更高) |
|
|
8.运算符优先级:
.、[]、new
()
++、--
!、~、正号、负号、typeof、void、delete
%、*、/
加号、减号
<<、>>、>>>
>、<、>=、<=
&
^
|
&&
||
?:
=、+=、-=、*=、/=、<<=、>>=、>>>=、&=、^=、|=
,
String prompt(“提示内容”)函数:弹出一个带有文本框的提示框,返回用户输入的内容,返回值为String类型
1.5 流程控制语句
1. if语句:
1 if(条件表达式1){ 2 语句1; 3 }else if(条件表达式2){ 4 语句2; 5 }else if(条件表达式n){ 6 语句n; 7 }else{ 8 语句n+1; 9 }
2. switch语句:可以省略语句和break语句,将条件串联起来
1 switch(条件表达式){ 2 case 条件1: 3 语句1; 4 break; 5 case 条件2: 6 语句2; 7 break; 8 …… 9 default: 10 语句n+1; 11 break; 12 }
3. while语句:
1 初始化循环变量; 2 while(条件表达式){ 3 循环体语句; 4 循环体后对循环变量的改变; 5 }
4. do while语句:
1 初始化循环变量; 2 do{ 3 循环体语句; 4 循环体后对循环变量的改变; 5 }while(条件表达式);
5. for语句:
1 for(初始化表达式;条件表达式;更新表达式){ 2 循环体语句; 3 }
6. break:结束switch代码块或跳出循环语句
7. continue:跳出本次循环的剩余步骤,继续下次循环
8. 通过为循环标号来实现结束指定循环或跳转到指定循环继续执行
1 1 标识符:for(){} //while和do while相同 2 2 break 标识符; //结束指定标号的循环 3 3 continue 标识符; //跳转到指定标号的循环继续执行
console.time(“计时器名”);计时器开始方法
console.timeEnd(“计时器名”);计时器停止方法
number Math.sqrt(被开方数);开放方法
1.6对象及函数
内建对象:ECMAScript标准定义的对象,在任何ECMAScript的实现中都可以使用
如:String、Number、Boolean、Object、Function、Math……
对象 宿主对象:JavaScript运行环境提供的对象,主要指浏览器
Object 如:BOM浏览器对象模型、DOM文档对象模型……
自定义对象:开发人员自定义的对象
1. 自定义对象的使用方法:
1 // 构造对象 2 var 对象名 = new Object(); 3 // 添加属性 4 对象名.属性名 = 属性值; 5 对象名[“属性名”] = 属性值; // 用于特殊属性名,如纯数字属性名等 6 // 修改属性 7 对象名.属性名 = 属性值; 8 // 调用属性 方法一 9 对象名.属性名; 10 // 调用属性 方法二 11 对象名[“属性名”]; // 更常用,属性名为常规属性名时,属性名外的引号可以省略 12 // 删除属性 13 delete 对象名.属性名;
未被构造的属性为undefined值
boolean “属性名” in 对象名:检查指定属性是否存在于指定对象
JavaScript程序的内存分配:
基本数据类型的变量以“名-值”的形式存储于栈中,先进后出
引用数据类型的变量以“名-地址值”的形式存储于栈中,地址值指向堆中的一块空间,数据实际存储于堆中
基本数据类型的变量传递的是值
引用数据类型的变量传递的是地址值,最终指向同一块堆空间
obj2 = null; //将obj2的值修改为null,不再指向堆中的空间,不影响堆中的数据和obj的地址值指向
var obj3 = new Object();
var obj4 = new Object();
obj3.name = “jerry”;
obj4.name = “jerry”; //obj3和obj4并没有关系,分别指向堆中不同的两块空间
比较基本数据类型时,比较值
比较引用数据类型时,比较地址值

栈(先进后出) 堆
1 // 使用对象字面量,创建对象的同时指定属性和属性值: 2 var obj = {属性名:属性值,属性名:属性值,……};
2. 函数:封装有功能代码的对象
1 // 创建函数 方法一:构造函数对象,将功能代码以字符串的形式作为形式参数传入 2 var fun = new Function("功能代码"); 3 // 创建函数 方法二:使用函数声明的方式创建函数 4 function fun(形式参数1,形式参数2,……){ 5 功能代码; 6 } 7 // 创建函数 方法三:使用函数表达式的方式创建函数 8 var fun = function(形式参数1,形式参数2,……){ 9 功能代码; 10 };
使用return语句返回函数的返回值,没有return语句或未指定return语句返回值的类型,默认返回undefined
匿名内部类:将一个匿名函数作为实际参数传入函数,匿名函数就是创建时未被函数表达式赋值给函数对象
立即执行函数:(匿名函数)(实际参数表);
调用函数时,解析器不会检查实际参数的数据类型,需要注意实际参数的数据类型是否为合法参数
调用函数时,解析器不会检查实际参数的数量,多余的实际参数会被舍弃,缺省的实际参数会被设置为undefined
当一个对象的属性为函数时,通过“对象名.函数名();”的方式调用这个函数,成为调用方法,没有本质区别
方法是封装在对象中的函数
3. for in语句:遍历对象中的所有属性
1 for(var 变量 in 对象){ 2 console.log(n + ":" + 对象[变量]); 3 }
1.7 作用域及this关键字
1. 全局作用域:在页面打开时创建,在页面关闭时销毁
(1) 全局作用域中存在一个全局对象window,代表浏览器的窗口,由浏览器创建,可以直接使用,全局变量作为windows对象的属性保存,函数作为window队形的方法保存
(2) 使用var关键字创建的变量将在所有代码执行前声明
(3) 使用函数声明方式创建的函数将在所有代码执行前创建,可以在创建函数的代码前调用
(4) 使用函数表达式方式创建的函数将在执行到创建函数的代码时创建,不可以提前调用
2. 函数作用域(局部作用域):在调用函数时创建,在函数执行完毕后销毁
(1) 就近原则:当在函数作用域中操作一个变量时,先在当前作用域中寻找变量,如果有就直接使用,如果没有就向上一级作用域寻找变量,直到找到为止,如果没有就报错
(2) 在函数中操作全局变量,使用“window.变量名”的形式
(3) 在函数中使用var关键字创建的变量将在函数内所有代码执行前声明,函数同理
(4) 在函数中未使用var关键字创建的变量将成为全局变量
(5) 函数的形式参数相当于在函数作用域中创建局部变量
3. 关键字this:本质是一个对象,用以全局作用域变量和函数作用域变量重名的问题,解析器每次调用函数时都会向函数传递的隐含参数this,谁调用该函数,this就指向谁
|
当以方法的形式调用时,this指向调用方法的对象 |
当以构造函数的形式调用时,this指向新构造的对象 |
|
当以函数的形式调用时,this指向全局对象window |
call和apply方法调用时,this指向c和a第一个参数 |
1.8 对象
1. 使用工厂方法批量创建对象:
1 //构造工厂方法: 2 function 工厂方法名(形式参数1,形式参数2,……){ 3 var obj = new Object(); 4 obj.实际参数1 = 形式参数1; 5 obj.实际参数2 = 形式参数2; 6 …… 7 var 对象方法名1 = function(){}; 8 var 对象方法名2 = function(){}; 9 …… 10 return obj; 11 } 12 // 调用工厂方法: 13 var obj1 = 工厂方法名();
缺点:使用工厂方法创建对象时,都调用Object类构造函数,创建的对象都是Object类型,不易于分辨出不同对象
2. 构造函数:使用同一个构造函数创建的对象称为一类对象,构造函数称为类,构造函数名命名规范遵循类名命名规范,首字母大写
1 //创建构造函数: 2 function 构造函数名(形式参数1,形式参数2,……){ 3 this.实际参数1 = 形式参数1; 4 this.实际参数2 = 形式参数2; 5 …… 6 this.对象方法名1 = function(){}; 7 this.对象方法名2 = function(){}; 8 …… 9 } 10 //调用构造函数: 11 var 对象名 = new 构造函数名();
构造函数的执行过程:
1.立即创建一个新的对象
2.this指向新创建的对象
3.逐行执行构造函数中的代码
4.将新创建的作为返回值返回
3. 原型对象prototype:
(1) 每个函数中都有一个隐含属性prototype,即原型对象
(2) 通过构造函数创建的对象中都有一个隐含属性_ _proto_ _,指向其构造函数的原型对象
(3) 原型对象用于设置一类对象共有的内容
(4) 如某个对象不需要原型对象中的共有内容,可以在对象中重写覆盖
(5) 原型对象也有原型对象,直到Object对象的原型对象,Object是所有对象的父类,没有Object的原型的原型
(6) 将一类对象的共有内容设置在构造函数中,将会为该构造函数创建的每一个对象创建一份共有内容,导致资源浪费;设置在全局作用域中,将浪费标识符,污染全局作用域

boolean 对象名.hasOwnProperty(“属性名”):检查指定对象自身是否含有指定属性,不包括原型对象中的内容
在JavaScript中,直接打印对象,实际打印的是对象的toString()方法的返回值,toString方法位于Object对象中,所以默认打印[object Object],如有需要可以在构造函数的原型对象中重写toString()方法
4. 垃圾回收(Garbage Collection,GC):如果没有任何变量引用一个对象,那么将永远无法操作该对象,该对象则成为垃圾,占用内存,延缓程序运行,JavaScript中有自动垃圾回收机制,不需要也不能进行干预,将不需要的对象赋值为null,则该对象就会失去引用,成为垃圾被回收
5. 内建对象 之 数组Array:索引自0开始,元素可以是任意数据类型,当嵌套数组时,称为二维数组
数组的使用方法:
1 // 使用字面量创建数组,并同时添加元素: 2 var 数组名 = [元素1,元素2,……]; 3 // 使用构造函数创建数组,并同时添加元素: 4 var 数组名 = new Array(元素1,元素2,……); 5 // 使用构造函数创建数组,并同时指定数组长度: 6 var 数组名 = new Array(数组长度); 7 // 添加元素: 8 数组名[索引] = 元素值; 9 // 调用元素: 10 数组名[索引]; 11 // 获取连续索引长度(元素个数)/获取非连续数组中最大索引+1: 12 number 数组名.length; 13 // 设置数组长度: 14 数组名.length = 数组长度; 15 // 向连续数组末尾添加元素: 16 数组名[数组名.length] = 元素值;
数组遍历:
在进行遍历时,循环变量标识符为i的原因是i是索引index的缩写
1 // 利用for循环遍历数组(常用) 2 for(var i = 0; i < 数组名.length; i++){ 3 console.log(数组名[i]); 4 } 5 // 使用forEach方法遍历数组(不常用,IE7及以下不兼容) 6 // 1.使用数组调用forEach()方法 7 // 2.向forEach()方法中传入一个函数作为参数,为不污染全局作用域,在参数中创建一个匿名函数 8 // 3.此匿名参数由开发人员创建,但自动调用,称为回调函数 9 // 4.回调函数会被自动调用数组中元素个数次,返回三个值VIA 10 // V:value,元素值 11 // I:index,索引 12 // A:array,数组 13 数组名.forEach(function(value,index,array){ 14 console.log(index + ":" + value); 15 });
数组方法:
|
number 数组名.push(元素1,元素2,……) |
向指定数组的末尾添加元素,并返回新的长度 |
|
number 数组名.unshift(元素1,元素2,……) |
向指定数组的开头添加元素,并返回新的长度 |
|
element 数组名.pop() |
删除并返回指定数组的最后一个元素 |
|
element 数组名.shift() |
删除并返回指定数组的第一个元素 |
|
Array 数组1.concat(数组2,数组3,……,元素1,元素2,……) |
连接数组和元素,并返回为一个新的数组 |
|
string 数组名.join(元素间连接符) |
将指定数组转换为字符串并返回,默认使用“,”连接 |
|
数组名.reverse() |
直接在原数组的基础上,反转指定数组 |
|
数组名.sort() |
将指定数组中的元素按Unicode编码排序,而不是数值 |
|
Array 数组名.slice(起始索引,结束索引) |
从指定数组中复制指定元素,并返回为一个新的数组 |
|
起始索引(包含),结束索引(不包含),省略表示从开始索引到最后一个元素,负值-n表示倒数第n个元素 |
|
|
Array 数组名.splice(起始索引,作用元素数量,元素1,元素2,……) |
|
|
从指定数组中剪切指定元素并返回为一个新的数组,同时在起始索引前插入新元素 |
|
|
可以省略新元素不插入只剪切,可以作用0个元素只插入,也可以同时操作 |
|
数组去重问题:
1 // 创建一个存在重复元素的数组,创建一个函数用于去重 2 var arr = [1,2,3,2,1,3,4,2,5]; 3 // 输出原数组 4 console.log(arr); 5 // 创建函数 6 function qvchong(arr){ 7 // 第一层循环,取出数组中的每一个元素 8 for(var i = 0; i < arr.length; i++){ 9 // 第二层循环,取出第一层循环取出元素后的所有元素 10 for(var n = i +1; n < arr.length; n++){ 11 // 如果取出的两个元素相等,则为重复 12 if(arr[i] == arr[n]){ 13 // 删除重复元素 14 arr.splice(n,1); 15 // !!!存在问题:删除一个重复元素后,下一个未经判断的元素自动补位,如果该补位元素依然重复,则未被去重!!! 16 // 解决方法:发生问题后,--一个索引,第二层循环再++一个索引,回到原处,重新判断去重位置上的元素 17 n--; 18 } 19 } 20 } 21 } 22 // 调用函数 23 qvchong(arr); 24 // 输出去重后的数组 25 console.log(arr);
自定义sort()方法排序规则:sort()方法默认按Unicode编码排序,而不是数组,对数值进行排序时会出现问题
例如:11排在2前面
1 // 向sort()方法中传入回调函数,用于指定排序规则 2 // 回调函数中需要两个形式参数,浏览器会分别使用数组中的元素作为实际参数,调用回调函数 3 // 使用哪个元素作为实际参数不确定,但是确定在数组中a在b的前边 4 // 浏览器会根据回调函数的返回值决定元素的顺序 5 // 返回值大于0,元素交换位置 6 // 返回值小于0,元素位置不变 7 // 返回值等于0,两个元素相等,位置不变 8 arr.sort(function(a,b){ 9 if(a > b){ 10 return 1; 11 }else if(a < b){ 12 return -1; 13 }else{ 14 return 0; 15 } 16 }); 17 // 优化 18 // 升序 19 arr.sort(function(a,b){ 20 return a-b; 21 }) 22 // 降序 23 arr.sort(function(a,b){ 24 return b-a; 25 })
6. 内建对象 之 函数对象的方法:call()方法和apply()方法
直接调用函数、使用函数对象调用call()方法、使用函数对象调用apply()方法都会执行函数
使用函数对象调用call()方法和apply()方法时,函数内的this指向call()方法和apply()方法的第一个实际参数
使用函数对象调用call()方法时,函数的实际参数为call()方法的第二及以后的实际参数
使用函数对象调用apply()方法时,函数的实际参数需要封装为数组,放在apply()方法的第二个实际参数
7. 内建对象 之 arguments对象:
本质是一个类数组对象,也可以像数组一样通过索引操作数据,使用length属性获取长度
解析器每次调用函数时都会向函数传递的隐含参数之二
调用函数时,传递的实际参数在arguments对象中保存
用于操作形式参数以外的实际参数
arguments.callee属性→对象→当前正在执行的函数
8. 内建对象 之 Date时间对象:
|
object Date() |
返回当前代码执行的日期和时间 |
|
object Date(“01/01/1970 00:00:00”) |
返回指定的日期和时间 |
|
number dateObject.getDate() |
返回dateObject是一个月中的第几天1~31 |
|
number dateObject.getDay() |
返回dateObject是一周中的第几天0~6,0表示周日 |
|
number dateObject.getMonth() |
返回dateObject是第几个月0~11 |
|
number dateObject.getFullYear() |
返回dateObject完整四位年份 |
|
number dateObject.getHours() |
返回dateObject小时数0~23 |
|
number dateObject.getMinutes() |
返回dateObject分钟数0~59 |
|
number dateObject.getSeconds() |
返回dateObject秒数0~59 |
|
number dateObject.getMilliseconds() |
返回dateObject毫秒数0~999 |
|
number dateObject.getTime() |
返回dateObject至01/01/1970 00:00:00 GMT的毫秒数,时间戳 |
|
number Date.now() |
返回当前时间戳 |
9. 内建对象 之 Math对象工具类:
Math对象中包含Math.PI、Math.E等常量
|
number Math.abs(x) |
返回x的绝对值 |
|
number Math.ceil(x) |
对x向上取整,并返回 |
|
number Math.floor(x) |
对x向下取整,并返回 |
|
number Math.round(x) |
对x四舍五入,并返回 |
|
number Math.random() |
返回0~1之间的随机数(包括0,不包括1) |
|
number Math.round(Math.random()*(y-x)+x) |
返回x~y之间的随机数(包括x和y) |
|
number Math.max() |
返回多个值中的最大值 |
|
number Math.min() |
返回多个值中的最小值 |
|
number Math.sqrt(x) |
返回x的平方根 |
|
number Math.pow(x,y) |
返回xy的值 |
10. 内建对象 之 包装类对象:
用于将基本类型的数据转换成对应的引用数据类型对象,以实现更丰富的操作
在使用toString()等方法将一个基本数据类型的数据转换为另一个基本数据类型时,基本数据类型并不是对象,其中并没用方法,而可以使用toString()等方法进行数据类型转换的原因是,浏览器自动将基本数据类型的数据临时转换为对应的引用数据类型对象,然后调用其中的方法
11. 内建对象 之 String对象中的方法:
在JavaScript底层,字符串是以字符数组的形式保存的,所以可以使用操作数组的方式操作字符串
|
number 字符串.length |
length属性,返回字符串长度 |
|
string 字符串.charAt(index) 等价于 字符串[index] |
返回指定字符串中指定索引上的字符 |
|
number 字符串.charCodeAt(index) |
返回指定字符串中指定索引上的字符的Unicode编码 |
|
string String.fromCharCode(Unicode编码) |
返回指定Unicode编码对应的字符 |
|
string 字符串1.concat(字符串2,字符串3,……) 等价于 + |
连接调用对象字符串和实际参数字符串,并返回 |
|
number 字符串.indexOf(“字符”) |
返回指定字符第一次出现的索引,返回-1代表不存在 |
|
number 字符串.indexOf(“字符”,index) |
返回指定字符自指定索引及以后出现的索引 |
|
number 字符串.lastIndexOf(“字符”) |
返回指定字符最后一次出现的索引,也可指定索引 |
|
array 字符串.split(“拆分依据字符串”) |
将指定字符串按拆分依据(不含)拆分成数组并返回 |
|
string 字符串.toUpperCase() |
将指定字符串转换为全部大写,并返回为一个新的字符串 |
|
string 字符串.toLowerCase() |
将指定字符串转换为全部小写,并返回为一个新的字符串 |
三种截取字符串的方法:
|
string 字符串.slice(起始索引,结束索引) |
从指定字符串中复制指定内容,并返回为一个新的字符串 |
|
起始索引(包含),结束索引(不包含),省略表示从开始索引到最后一个字符,负值-n表示倒数第n个字符 |
|
|
string 字符串.substring(起始索引,结束索引) |
从指定字符串中复制指定内容,并返回为一个新的字符串 |
|
起始索引(包含),结束索引(不包含),省略表示从开始索引到最后一个字符,不能为负值,结束<开始时自动交换 |
|
|
string 字符串.substr(起始索引,复制长度) |
从指定字符串中复制指定内容,并返回为一个新的字符串 |
|
非ECMAScript标准,不建议使用 |
|
12. 内建对象 之 正则表达式Regular Expression:
表示字符串正确规则的式子,用于计算机识别字符串是否符合规则或从字符串中获取指定内容
灵活 使用构造函数创建正则表达式对象:var 标识符 = new RegExp(“正则表达式”,“匹配模式”);
简便 使用字面量创建正则表达式对象:var 标识符 = /正则表达式/匹配模式
1.9 正则表达式
|
Abc |
检测字符串中是否存在连续的Abc,区分大小写 |
|
A|b|c 等价于 [Abc] |
检测字符串中是否存在A或b或c,区分大小写 |
|
[a-z] |
检测字符串中是否存在任意小写字母 |
|
[A-Z] |
检测字符串中是否存在任意大写字母 |
|
[A-z] |
检测字符串中是否存在任意大小写英文字母或者一些符号,Z和a中间是一些符号 |
|
a[A-z]b |
检测字符串中是否以a开头,以b结尾,中间有一个任意大小写英文字母 |
|
[^ab] |
检测字符串中是否不存在连续的ab,区分大小写 |
|
[0-9] |
检测字符串中是否存在阿拉伯数字 |
|
(ab){m,n} 等价于 ababab |
检测字符串中是否存在至少m,至多n个连续的ab,区分大小写,m和n可省略 |
|
a+ 等价于 a{1,} |
检测字符串中是否存在至少一个a,区分大小写 |
|
a* 等价于 a{0,} |
检测字符串中是否含有任意个a,区分大小写 |
|
a? 等价于 a{0,1} |
检测字符串中是否含有一个a,或不含有a,区分大小写 |
|
^(ab) |
检测字符串是否以ab开头,区分大小写 |
|
(ab)$ |
检测字符串是否以ab结尾,区分大小写 |
|
^a$ |
检测字符串是否完全为a,区分大小写 |
|
. |
表示一个任意字符 |
|
\ |
转义字符 |
|
\w |
word,任意字母、数字、下划线 |
|
\W |
word,非字母、数字、下划线 |
|
\d |
digit,任意数字 |
|
\D |
digit,非数字 |
|
\s |
space,空格 |
|
\S |
space,非空格 |
|
\b |
border,单词边界 |
|
\B |
border,非单词边界 |
1. 基础中国手机号码正则表达式:/^1[3-9][0-9]{9}$/
(1) 以1开头
(2) 第二位为3-9(包含)的任意数字
(3) 共11位数字
2. 匹配模式:
|
i |
ignored,忽略大小写 |
|
g |
global,全局匹配模式,检测整个字符串并进行操作 |
|
ig 等价于 gi |
忽略大小写全局匹配模式 |
boolean 正则表达式.test(字符串);使用指定正则表达式检测指定字符串是否符合规则
3. 正则表达式可以作为实际参数搭配函数和方法使用:
|
array 字符串.split(拆分依据) |
将指定字符串按拆分依据(不含)拆分成数组并返回 |
|
number 字符串.search(搜索内容) |
在指定字符串中搜索指定内容,并返回第一次出现的索引,若不存在返回-1 |
|
array 字符串.match(匹配内容) |
在指定字符串中搜索指定内容,并返回第一次出现的内容,若不存在返回空数组 |
|
string 字符串.replace(旧,新) |
将指定字符串中的指定内容替换成指定内容,并返回为一个新的字符串 |
split自动全局匹配,search不能全局匹配,match和replace可以手动设置全局匹配,默认非全局匹配
2 DOM
2.1 简介
宿主对象 之 DOM,Document Object Model,文档对象模型:
JavaScript通过DOM操作HTML文档,即HTML页面
HTML页面中的每一个部分都转换成为一个对象,便于面向对象操作
模型表示对象之间的关系,便于寻找对象

2.2 节点
1. 节点node:构成HTML文档最基本的单元
文档节点document:整个HTML文档,window对象的属性对象,可以通过document直接使用
元素节点element:一个元素标签
属性节点attribute:标签的一个属性
文本节点text:标签的文本内容
|
|
nodeName节点名 |
nodeType节点类型 |
nodeValue节点值 |
|
文档节点document |
#document |
9 |
null |
|
元素节点element |
标签名 |
1 |
null |
|
属性节点attribute |
属性名 |
2 |
属性值 |
|
文本节点text |
#text |
3 |
文本内容 |
2. 获取元素节点:
|
object document.getElementById(“标签id”) |
通过标签id获取一个元素节点对象 |
|
类数组对象 document.getElementsByTagName(“标签名”) |
通过标签名获取一组元素节点对象 |
|
类数组对象 document.getElementsByName(“name属性值”) |
通过name属性获取一组元素节点对象 |
|
object document.getElementsByXxxx(“”)[0] |
获取一组元素节点对象中的一个对象 |
3. 获取元素节点的子节点:
|
类数组对象 元素节点对象.getElementsByTagName(“标签名”) |
通过标签名获取一组元素节点对象 |
|
类数组对象 元素节点对象.childNodes |
获取元素节点对象的所有子节点对象 包括文本节点和元素节点,IE8及以下兼容差 |
|
object 元素节点对象.childNodes[index] |
获取元素节点对象的指定索引子节点对象 |
|
类数组对象 元素节点对象.children |
获取元素节点对象的所有子元素对象 |
|
object 元素节点对象.firstChild |
获取元素节点对象的第一个子节点对象 包括文本节点 |
|
object 元素节点对象.firstElementChild |
获取元素节点对象的第一个子元素对象 IE8及以下不兼容 |
|
object 元素节点对象.lastChild |
获取元素节点对象的最后一个子节点对象 包括文本节点 |
|
object 元素节点对象.lastElementChild |
获取元素节点对象的最后一个子元素对象 IE8及以下不兼容 |
4. 获取元素节点的关系节点:
|
object 元素节点对象.parentNode |
获取元素节点对象的父节点对象 |
|
object 元素节点对象.previousSibling |
获取元素节点对象的前一个兄弟节点对象 包括文本节点,IE8及以下不兼容 |
|
object 元素节点对象.nextSibling |
获取元素节点对象的后一个兄弟节点对象 包括文本节点,IE8及以下不兼容 |
5. 获取其他节点:
|
object document.body |
获取body元素对象 |
|
object document.documentElement |
获取html元素对象 |
|
类数组对象 document.all |
获取全部元素对象(过时) |
|
类数组对象 document.getElementsByClassName(“class”) |
通过标签class获取一组元素节点对象,IE8及以下不兼容 |
|
object document.querySelector(“CSS选择器”) |
通过CSS选择器获取一个元素节点对象,常用 IE7及以下不兼容 |
|
类数组对象 document.querySelectorAll(“CSS选择器”) |
通过CSS选择器获取一组元素节点对象,常用 IE7及以下不兼容 |
6. 元素节点对象的属性:元素节点对象.属性名(class属性:元素节点对象.className)
ElementNode.innerHTML元素节点的内容属性,包含HTML标签,自结束标签没有内容属性
ElementNode.innerText元素节点的文本属性,不含HTML标签
文本节点.nodeValue文本节点的文本内容
2.3 事件
1. 事件:用户和HTML文档或浏览器之间发生的交互行为,为事件绑定响应函数,事件发生时响应函数将被调用
代码耦合方式:将响应作为属性设置在标签内
独立文件方式:获取元素节点对象,设置元素节点对象的事件属性为响应函数,设置响应函数功能
浏览器在解析页面时遵从自上而下的顺序,如果JavaScript代码置于标签前,JavaScript代码执行时元素节点还没有创建,导致获取对象失败,程序报错
将JavaScript标签置于body标签内,</body>标签前
将JavaScript代码写在window对象的onload属性对应的响应函数内
|
object document.createElement(“标签名”) |
创建指定标签名的元素节点对象 |
|
object document.createTextNode(“文本内容”) |
创建指定内容的文本节点对象 |
|
父节点.appendChild(子节点) |
将指定子节点对象插入到指定父节点对象下 |
|
父节点对象.innerHTML += “新内容” |
向父节点对象中添加新代码, 将会影响父节点中的所有代码,结合以上使用 |
|
父节点.insertBefore(新子节点,指定子节点) |
在指定子节点前插入新子节点 |
|
父节点.replaceChild(新子节点,旧子节点) |
用新子节点替换旧子节点 |
|
object 父节点.removeChild(子节点) 等价于 object 子节点.parentNode.remove(子节点) |
删除指定父节点下的指定子节点 并返回子节点 |
点击超链接后,跳转页面,是超链接的默认行为,如果不需要,在超链接的单击响应函数末尾添加return false;
弹出带有确定按钮和取消按钮的警告框:boolean confirm(“内容”);
2. 通过JavaScript读取或修改样式:
|
元素节点对象.style.样式名 = “样式值”; |
修改HTML代码中的内联样式 |
|
string 元素节点对象.style.样式名 |
返回HTML代码中的内联样式 |
|
string 元素节点对象.currentStyle.样式名 |
返回当前显示的样式,当样式为默认值时,返回默认值,仅兼容IE |
|
object getComputedStyle.(元素节点对象,伪元素/一般为null) |
返回当前显示的样式对象,当样式为默认值时,返回实际值,IE8及以下不兼容 |
|
string getComputedStyle.(元素节点对象.伪元素/一般为null).样式名 |
返回当前显示的样式,当样式为默认值时,返回实际值,IE8及以下不兼容 |
|
以上返回高度、宽度等样式时,返回数值+单位的字符串,以下返回高度、宽度等时,返回数值 |
|
|
number 元素节点对象.clientWidth |
返回内容区宽度+左右内边距的数值 |
|
number 元素节点对象.clientHeight |
返回内容区高度+上下内边距的数值 |
|
number 元素节点对象.offsetWidth |
返回可见区宽度的数值 |
|
number 元素节点对象.offsetHeight |
返回可见区高度的数值 |
|
object 元素节点对象.offsetParent |
返回当前元素的定位容器对象 即离当前元素最近的,开启定位的祖先元素 若所有祖先元素均未开启定位,则返回body |
|
number 元素节点对象.offsetLeft |
返回当前元素相对于定位容器对象的水平偏移量,向右偏移为正 |
|
number 元素节点对象.offsetTop |
返回当前元素相对于定位容器对象的垂直偏移量,向下偏移为正 |
|
number 元素节点对象.scrollWidth |
返回滚动部分宽度 |
|
number 元素节点对象.scrollHeight |
返回滚动部分高度 |
|
number 元素节点对象.scrollLeft |
返回水平滚动距离 |
|
number 元素节点对象.scrollTop |
返回垂直滚动距离 |
当显示滚动条时,滚动条将遮挡一部分内容,导致clientWidth和clientHeight减小
当scrollHeight – scrollTop == clientHeight时,表示滚动条滚动到底部,水平方向同理
整个页面的滚动条属于HTML标签,也就是document.documentElement对象
在JavaScript中,含有-的样式名不合法,需要修改为驼峰命名法:去掉-,并将-后的首字母大写,如background-color
1 // 自定义函数,用于读取样式值,并兼容所有浏览器 2 // 参数列表1:obj元素节点对象 3 // 参数列表2:name样式名 4 function getStyle(obj , name){ 5 // 判断浏览器为IE8及以下或正常浏览器 6 // 判断条件为window对象的getComputedStyle属性,而非getComputedStyle()方法对象 7 // 当判断条件为属性时,存在则返回值,转换为true;不存在则返回false 8 // 当判断条件为对象时,存在则返回值,转换为true;不存在则报错 9 if(window.getComputedStyle){ 10 // 存在getComputedStyle()方法对象的正常浏览器,使用getComputedStyle()方法,并返回样式值 11 // getComputedStyle(obj , null).name时,寻找name属性,使用[]强调name是变量 12 return getComputedStyle(obj , null)[name]; 13 }else{ 14 // 不存在getComputedStyle()方法的IE8及以下浏览器,使用currentStyle属性,并返回样式值 15 return obj.currentStyle[name]; 16 } 17 } 18 // 使用三元运算符简化 19 function getStyle(obj , name){ 20 return window.getComputedStyle?getComputedStyle(obj , null)[name]:obj.currentStyle[name]; 21 } 22 var btn = document.getElementById("btn"); 23 btn.onclick = function(){ 24 var box = document.getElementById("box"); 25 alert(getStyle(box , "backgroundColor")); 26 }
3. 事件:
|
元素节点对象.onclick |
当元素节点对象被鼠标左键单击时 |
|
元素节点对象.ondbclick |
当元素节点对象呗鼠标左键双击时 |
|
元素节点对象.onscroll |
当元素节点对象的滚动条被滚动时 |
|
元素节点对象.onmousemove |
当鼠标指针在元素节点对象上移动时 |
|
元素节点对象.onmousedown |
当鼠标左键按下时 |
|
元素节点对象.onmouseup |
当鼠标左键抬起时 |
|
元素节点对象.onwheel |
当鼠标滚轮滚动时(待定) |
|
元素节点对象.onkeydown |
当键盘的某个按键按下时 |
|
一般绑定document或可获取焦点的对象,onkeyup同 当键盘的按键被一直按下时,onkeydown事件将会一直触发,并且第一次和第二次的间隔较大 |
|
|
元素节点对象.onkeyup |
当键盘的某个按键抬起时 |
4. 事件对象:当事件响应函数被触发时,浏览器会将一个事件对象作为实际参数传入事件响应函数,在事件对象中封装了当前事件的一切信息,通过在事件响应函数中设置形式参数使用事件对象及信息
IE8及以下不会将事件对象作为实际参数传入事件响应函数,而是作为window对象的一个属性
Firefox不会将事件对象作为window对象的一个属性,而其他浏览器同时兼容两种形式
1 // 同时兼容Firefox和IE8及以下 2 元素节点对象.事件 = function(event){ 3 // 判断event变量是否存在,如果不存在,则使用window.event替换event 4 if(!event){ 5 event = window.event; 6 } 7 // 使用或运算符简化 8 // 或运算符先判断第一个条件是否为true,如果是,则不判断第二个条件,返回true;否则判断第二个条件 9 event = event || window.event; 10 }
|
number 事件对象.clientX |
返回相对于可见窗口的鼠标指针横坐标 |
|
number 事件对象.clientY |
返回相对于可见窗口的鼠标指针纵坐标 |
|
number 事件对象.pageX |
返回相对于页面的鼠标指针横坐标, IE8及以下不兼容 |
|
number 事件对象.pageY |
返回相对于页面的鼠标指针纵坐标, IE8及以下不兼容 |
|
object 事件对象.target |
返回触发此事件的元素节点对象 |
|
number 事件对象.keyCode |
返回按下的键盘按键的按键编码 |
|
boolean 事件对象.altKey |
返回alt键是否被按下,如果是返回true,否则返回false |
|
boolean 事件对象.ctrlKey |
返回ctrl键是否被按下,如果是返回true,否则返回false |
|
Boolean 事件对象.shiftKey |
返回shift键是否被按下,如果是返回true,否则返回false |
5. 事件冒泡Bubble:事件向上传导,当后代元素的事件被触发时,其祖先元素的相同事件也会被依次触发
如果不需要冒泡,可以在事件响应函数中,通过事件对象取消:event.cancelBubble = true;
6. 事件委派:将多个元素共同的响应函数绑定给共同的祖先元素,当后代元素上的事件被触发时,将利用事件冒泡传递给祖先元素,通过祖先元素的响应函数处理事件,能减少事件响应函数绑定次数,提高性能
为一个元素节点对象同时绑定多个相同的事件,并按照绑定顺序执行:
|
元素节点对象.addEventListener(“事件名删on”,响应函数,是否在捕获阶段触发事件一般为false); |
IE8及以下不兼容 |
|
元素节点对象.attachEvent(“事件名”,响应函数) |
仅兼容IE |
1 // 自定义函数,用于为指定元素节点对象绑定多个相同事件的响应函数,并同时兼容所有浏览器 2 // 参数列表1:obj指定元素节点对象 3 // 参数列表2:eventStr事件名删on,拼串只需拼串运算符,拆串需要函数或方法 4 // 参数列表3:fun响应函数 5 function bind(obj, eventStr, fun) { 6 // 在addEventListener()方法中,this指元素节点对象 7 // 在attachEvent()方法中,this指window 8 if (obj.addEventListener) { 9 obj.addEventListener(eventStr, fun, false); 10 } else { 11 obj.attachEvent("on" + eventStr, function () { 12 fun.call(obj); 13 }); 14 } 15 } 16 var btn = document.getElementById("btn"); 17 bind(btn, "click", function () { 18 alert(this); 19 })
7. 事件传播:关于事件传播,网景Netscape、微软Microsoft、W3C有不同的理解
(1) 网景Netscape:事件触发时,先触发最外层的祖先元素的事件,然后向内传播,直到最内层的后代元素
(2) 微软Microsoft:事件触发时,先触发最内层的后代元素的事件,然后向外传播,直到最外层的祖先元素
(3) W3C:综合网景Netscape和微软Microsoft,将事件传播分为三个阶段
捕获阶段:从最外层的祖先元素向内捕获,直到最内层的后代元素,但捕获阶段默认不会触发事件
目标阶段:捕获实际到触发事件的元素节点对象,捕获阶段结束,在元素节点对象上触发事件
冒泡阶段:从最内层的后代元素向外触发,直到最外层的祖先元素
如果希望在捕获阶段就触发事件,将addEventListener()中的第三个参数设置为true,一般为false
IE8及以下没有捕获阶段
当在浏览器中拖动选中内容到标签栏中时,浏览器会自动在搜索引擎中搜索选中内容,会导致拖拽效果异常,在onmousedown事件的响应函数中设置return false解决,IE8及以下不兼容
在IE中使用元素节点对象.setCapture()和元素节点对象.releaseCapture(),捕获鼠标的所有事件,甚至是在浏览器窗口外的,并绑定给元素节点对象的响应函数,然后释放捕获
1 // 自定义函数,为指定的元素节点对象绑定拖拽效果,并同时兼容所有浏览器 2 // 参数列表1:obj指定元素节点对象 3 function drag(obj) { 4 if(obj.setCapture) 5 obj.onmousedown = function (event) { 6 // 当在浏览器中拖动选中内容到标签栏中时,浏览器会自动在搜索引擎中搜索选中内容,会导致拖拽效果异常 7 // 在onmousedown事件的响应函数中,调用obj.setCapture()解决,仅兼容IE 8 if(obj.setCapture){ 9 obj.setCapture(); 10 } 11 // 与运算符先判断第一个条件是否为true,如果是,则继续判断第二个条件并返回;否则直接返回false 12 // 使用与运算符简化 13 obj.setCapture && obj.setCapture; 14 // 当按下鼠标左键开始拖拽时,记录鼠标指针在元素节点对象中的相对位置 15 // style.left和style.top的返回值是带有单位的字符串,所以选用offsetLeft和offsetTop 16 event = event || window.event; 17 var x = event.clientX - obj.offsetLeft; 18 var y = event.clientY - obj.offsetTop; 19 document.onmousemove = function (event) { 20 event = event || window.event; 21 // 减去偏移量,恢复鼠标指针在元素节点对象中的相对位置 22 var left = event.clientX - x; 23 var top = event.clientY - y; 24 obj.style.left = left + "px"; 25 obj.style.top = top + "px"; 26 } 27 document.onmouseup = function () { 28 document.onmousemove = null; 29 document.onmouseup = null; 30 // 当鼠标松开时,取消对事件的捕获,并使用与运算符简化 31 obj.releaseCapture && obj.releaseCapture(); 32 } 33 // 当在浏览器中拖动选中内容到标签栏中时,浏览器会自动在搜索引擎中搜索选中内容,会导致拖拽效果异常 34 // 在onmousedown事件的响应函数中设置return false解决,IE8及以下不兼容 35 return false; 36 } 37 }
3 BOM
3.1简介
宿主对象 之 BOM,Browser Object Model,浏览器对象模型:
JavaScript通过BOM操作浏览器
|
BOM对象 |
含义 |
用途 |
|
Window |
整个浏览器窗口 |
页面全局对象 |
|
Navigator |
当前浏览器信息 |
识别不同的浏览器 |
|
Location |
浏览器地址栏信息 |
获取地址栏信息,跳转页面 |
|
History |
浏览器历史记录 |
操控历史记录,由于隐私问题,不能获取全部历史记录,只能操控浏览器向前/向后翻页,且只在当次访问有效 |
|
Screen |
用户显示器信息 |
获取用户的显示器信息 |
除Window外,其他对象均作为Window对象的属性保存,即刻通过Window对象的属性使用,也可直接使用
3.2 Navigator
由于历史原因,Navigator的大部分属性已经不能用于获取浏览器信息
string navigator.userAgent属性,返回一个用于识别浏览器的字符串,除IE11外均包含浏览器名称,使用正则表达式提取
|
谷歌浏览器 |
/chrome/i |
|
火狐浏览器 |
/firefox/i |
|
微软浏览器 |
/msie/i |
IE11为伪装,去除了navigator.userAgent返回值字符串中的有效标识
通过判断是否存在IE特有对象window.ActiveXObject来判断是否是IE
IE11为伪装,将!!window.ActiveXObject的值设定为false
使用ActiveXObject in window的返回值来判断是否是IE
1 if(/chrome/i.test(navigator.userAgent)){ 2 alert("chrome"); 3 }else if(/firefox/i.test(navigator.userAgent)){ 4 alert("firefox"); 5 }else if(ActiveXObject in window){ 6 alert("IE"); 7 }
3.3 History
number history.length属性,返回当次访问的页面数量
|
history.back() |
回退当上一个页面,作用与浏览器的回退按钮相同 |
|
history.forword() |
前进到下一个页面,作用于浏览器的前进按钮相同 |
|
history.go(整数) |
向前/后跳转指定个数页面,正表示向前,负表示向后 |
3.4 Location
直接读取location对象,返回当前地址栏信息
修改location对象为绝对路径、相对路径、域名、IP地址等字符串,跳转到指定页面
string location.href属性,用途与location对象相同
|
location.reload() |
重新加载当前页面,以true作为参数,将会清空缓存 |
|
location.assign(string) |
以地址信息作为参数,跳转到其对应的页面,同时生成历史记录,可以回退 |
|
location.replace(string) |
以地址信息作为参数,跳转到其对应的页面,不生成历史记录,不能回退 |
3.5 Screen
多用于移动端,待定
3.6 Window
定时器使用前,先关闭,防止开始多个定时器,导致无法关闭
|
number setInterval(Function,number) |
设置一个定时器,每间隔指定毫秒数,执行一次函数,并返回一个数字作为定时器唯一标识,用于关闭定时器 |
|
clearInterval(number) |
可以使用任意数值作为参数,如果参数是定时器标识,则关闭指定定时器;否则无动作,也不会报错 |
|
number setTimeout(Function,number) |
设置一个延时器,等待指定毫秒数后,仅执行一次函数,并返回一个数字作为延时器唯一标识,用于关闭延时器 |
|
clearTimeout(number) |
可以使用任意数值作为参数,如果参数是延时器标识,则关闭指定延时器;否则无动作,也不会报错 |
通过修改元素节点对象的style属性来修改样式,每次修改时,浏览器都需要重新渲染页面,执行性能低,耦合度高,编码复杂,通过修改元素节点对象的className属性来修改元素的class属性,间接修改样式,可以同时修改多个样式,浏览器只需渲染一次,执行性能好,表现与行为分离,同时也能通过向className属性中+= 属性名的形式追加样式
3.7 JSON
1. JSON,JavaScript Object Notation,JavaScript对象表示法,是一种特殊格式的字符串,通过使用JavaScript语法,在前后端的不同语言之间传递数据
2. JSON对象字符串用单引号括起,格式与JavaScript对象字面量相同,属性名用双引号括起
3. JSON数组字符串用单引号括起,格式与JavaScript数组字面量相同
4. JSON中允许的值包括:String、Number、Boolean、Null、Object、Array,但不包括函数
|
object JSON.parse(JSON字符串) |
将JSON字符串解析为JavaScript对象、数组等允许值 |
|
string JSON.stringify(object) |
将JavaScript对象转换为JSON字符串 |
5. IE7及以下不兼容JSON,当需要兼容IE7及以下时,引入JSON代码
6. eval(string)
(1) 执行指定字符串中的代码和赋值表达式,并返回执行结果
(2) 如果指定字符串中含有{},eval()函数将会把{}中的内容视为代码块
(3) 如果不希望eval()函数将{}中的内容视为代码块,则将字符串用()括起
(4) eval()函数功能过于强大,在开发中尽量不要使用,存在安全隐患,且效率较低

浙公网安备 33010602011771号