一、语法:
1.导入JS代码或文件:
(1)行内,将js代码写在html标签属性值中:
<input type="button" value="按钮" onclick="js代码" />
(2)内嵌,将js代码写在<script></script>中:
<head>
<script>
...<!-- js代码 -->
</script>
</head>
(3)引入外部js文件:
<head>
<script src="文件名称.js"></script>
</head>
2.JS注释:
//单行注释
/*
多行注释
*/
3.变量(变量名可以由字母、数字(不能用在开头)、_、$组成):
(1)声明变量:
var 变量名; //值为undefined
或
var 变量名 = 值; //根据值确定变量类型
或
变量名 = 值; //根据值确定变量类型
(2)全局变量,定义在函数外:
<script>
var 变量名 = 值; //全局变量
</script>
(3)局部变量,定义在函数内:
<script>
function 函数名(){
var 变量名 = 值; //局部变量
}
</script>
(4)块级作用域(ES6新增),定义在代码块中:
<script>
function 函数名(){
if(表达式){
var 变量名 = 值; //定义在代码块中,此变量只允许在if代码块内部使用
}
}
</script>
(5)闭包Closure:
b函数访问a函数中的局部变量,叫闭包。
例:
function a(){
var a = 0;
function b(){
var b = a; //访问了a函数的变量a
}
}
(6)let,声明的变量只能在当前代码块区域有效(ES6新增):
if(...){
let x = 1; //变量x作用域为if代码块
}
(7)const,声明的常量只能在当前代码块区域有效(ES6新增):
if(...){
const x = 1; //常量x作用域为if代码块,必须有初值,后面不能改值
}
(8)解构赋值(ES6新增):
数组解构:
let [变量名1, 变量名2]arr = [值1, 值2]; //将值赋值给变量,按顺序赋值
或
let [变量名1, ...变量名n]arr = [值1, 值2, 值n]; //将值赋值给变量,按顺序赋值
对象解构:
let 对象名 = {属性名1: 属性值1, 属性名2: 属性值2}; //定义对象
方式1:
let {变量名1, 变量名2} = 对象名; //将对象属性值赋值给变量,按顺序赋值
方式2:
let {属性名1: 变量名1, 属性名2: 变量名2} = 对象名; //将对象属性值赋值给变量,冒号左侧为属性名,右侧为变量名
4.数据类型与类型转换(运行时才确定类型):
(1)undefined类型,只声明没有赋值:
var x;
(2)null类型,显式赋值为null:
var x = null;
(3)NaN为非数值类型:
var x;
数值 + x; //结果为NaN,将不能转的字符串转为数值型时也会返回NaN类型
isNan(数值); //判断是否非数字,值为true或false
(4)number类型,包含整型与浮点型,默认值为0,Infinity为无穷大,-Infinity为无穷小:
var x = 数值; //十进制
var x = 0数值; //八进制,首位加0
var x = 0x数值; //十六进制,首位加0x
数值.parseInt("字符串"); //将字符串强转为数值
数值.parseFloat("字符串"); //将字符串强转为数值
Number("字符串"); //将字符串强转为数值
"字符串" - 数值 //将字符串隐式转为数值,支持的算术运算符:- * /
(5)boolean类型,值为true或false,默认值为false:
var x = false;
Boolean(其他类型值); //转为boolean类型,非空值转换时为true,空值转换时值为false:''、""、0、NaN、null、undefined
(6)string类型,默认值为"":
var x = "x";
var x = 'x';
var x = "a'b'c"; //字符串内部包含带引号的字符串
var x = 'a"b"c'; //字符串内部包含带引号的字符串
var x = "x" + 任意类型值; //字符串拼接(隐式转换),字符串+NaN为NaN,字符串+undefined为undefined,字符串+null为字符串null,
变量.toString(); //强转为字符串
String(变量) //强转为字符串
\n:换行符
\\:斜杠\
\':单引号'
\":双引号"
\t:tab缩进
\b:空格
5.运算符:
(1)算术运算符:
* / % + -
变量++、++变量、变量--、--变量 //实现变量自加或自减
(2)逻辑运算符:
< > >= <=
==、=== //等号,==当值一致为true(会自动转换类型),===当类型与值都一致为true
!=、!== //不等号,!=当值不一致为true(会自动转换类型),!==当类型或值不一致为true
&& || //逻辑与、逻辑或,短路效果,左侧满足后不计算右侧
! //逻辑非,例:!变量
(3)赋值运算符:
= += -= *= /= %=
(4)优先级(从上往下):
()
++、--、!
*、/、%、+、-
>、>=、<、<=
==、!=、===、!==
&&、||
=
,
6.流程控制:
(1)if语句:
if (条件表达式1) {
...
} else if (条件表达式2) {
...
} else {
...
}
(2)三元表达式:
var x = 条件表达式 ? 执行语句1 : 执行语句2;
(3)switch语句:
switch(条件表达式){ //表达式值与case值比较
case 值1:
...
break;
case 值2:
...
break;
default:
...
}
7.循环:
(1)for循环:
for (var i=0; i <= 最大数值; i++) {
...
}
(2)while循环:
while (条件表达式) {
...
}
(3)do...while循环:
do {//先执行一次
...
} while (条件表达式) //条件满足才执行下一次
(4)提前跳出循环:
while (条件表达式) {
if(条件表达式1){
continue; //跳出本次循环,进入下一次
}
if(条件表达式2){
break; //退出所有循环
}
}
8.数组(数组也属于对象):
var list = new Array(); //创建空数组
var list = []; //创建空数组
var list = [值1, 值2, 值3]; //创建并初始化数组元素
var x = list[下标数值]; //取出数组指定下标的值
list[下标数值] = 新值; //给数组指定下标赋新值
var len = list.length; //获取数组长度
list.length = 新长度数值; //修改数组长度
9.函数(函数也属于对象):
(1)定义与调用(支持函数内部再定义与调用子函数):
方式1(普通函数,内部this指向window对象):
function 函数名(参数名1, 参数名2) { //参数可以没有,也可以一个或多个
...
return 值; //不需要返回值时可以省略此句
//return 值1, 值2; //返回最后一个值2
}
方式2(匿名函数,实际上没有函数名):
var 函数名 = function(){
...
}
方式3:
var 函数名 = new Function(参数名1, 参数名2, "函数体表达式"); //将函数内部代码写在第3个参数中
调用:
函数名(值1, 值2);
函数名.call(this, 值1, 值2, ...);
类名.函数名.call(this, 值1, 值2, ...); //调用函数并改变函数内部this指向
函数名.apply(this, 数组);
类名.函数名.apply(this, 数组); //调用函数并改变函数内部this指向
(2)arguments存了所有参数值,为数组,下标从0开始:
function 函数名() {
var x1 = arguments[0]; //获取参数1的值
var x2 = arguments[1]; //获取参数2的值
}
(3)立即执行函数(执行到此行时将调用函数,内部this指向window对象):
(function(){
...
})();
(4)bind方法,改变函数内部this指向:
函数名.bind(this或控件引用, 值1, 值2, ...); //可以在函数内使用传入的this
或
函数名(function(){
//可以在函数内使用传入的this
this.属性 = 新值;
}.bind(this));
(5)高阶函数:
方式1:
function 函数1(callback){ //callback接收一个函数作为参数
...
}
函数1(function(){...}) //调用函数1时传入了一个函数,函数1称为高阶函数
方式2:
function 函数1(){
return function(){...} //返回了一个函数,函数1称为高阶函数
//return 函数名;
}
(6)箭头函数(ES6新增):
箭头函数内的this指向函数定义处的this(箭头函数外层this)
方式1:
const 函数名 = (形参1, 形参2) => { //小括号放形参(可以没有形参)
//大括号放函数体
}
方式2:
const 函数名 = (形参1, 形参2) => 一行函数体; //当函数体只有一行且带return时,可以省略大括号,不用写return
方式3:
const 函数名 = 形参1 => 一行函数体; //当形参只有一个时,可以省略小括号
(7)剩余参数(ES6新增):
定义:
function 函数名(形参1, ...args){ //以...args定义形参2等剩余形参
}
或
const 函数名 = (...args) => { 以...args定义所有形参
}
调用:
函数名(实参1, 实参2, 实参3); //可以传入多个实参
10.开启严格模式:
严格模式说明:
变量必须先用var声明再使用;
不能使用delete删除已定义的变量(删除变量:delete 变量名);
this指向undefined(非严格模式this指向window);
调用函数时必须使用new(new 函数名());
系统函数的this依旧指向window;
事件/对象依旧指向调用者;
不允许函数形参同名;
函数定义必须在<script>标签顶层或函数内。
(1)为整个文件代码开启严格模式:
方式1:
<script>
'use strict'; //后面的代码会执行严格模式
</script>
方式2:
<script>
(function(){
'use strict'; //后面的代码会执行严格模式
})();
</script>
(2)为某个函数代码开启严格模式:
function 函数名(){
'use strict'; //后面的代码会执行严格模式
}
二、对象:
this指向实例对象本身
1.定义对象(ES5):
(1)方式1:
var 对象名 = {}; //创建空对象
var 对象名 = { //创建有属性与函数的对象
属性名1: 属性值1, //对象属性
属性名2: 属性值2,
方法名: function(){ //对象方法(就是函数)
...
}
}
(2)方式2(使用new创建):
var 对象名 = new Object(); //创建对象
对象名.属性名 = 属性值; //为对象创建属性
对象名.方法名 = function(){ //为对象创建方法
...
}
2.调用对象:
var x = 对象名.属性名; //获取对象的属性值
var x = 对象名['属性名']; //获取对象的属性值
对象名.方法名(); //调用对象的方法
3.用构造函数创建对象(ES5):
(1)定义构造函数(构造函数首字母大写,不需要return):
function 构造函数名(参数1, 参数2){ //参数可以没有,也可以有一个或多个
this.属性名1 = 参数1; //为对象创建属性,并赋值
this.方法名 = function(){ //对象方法
...
}
}
(2)创建构造函数的对象:
var obj = new 构造函数名(值1, 值2); //调用多次new就会创建多个对象
(3)创建构造函数的静态属性:
构造函数名.属性名 = 值;
4.遍历对象属性列表:
for(var key in 对象名){ //每次循环会获取一个属性名赋值给key变量
var x = 对象名[变量名]; //获取对象属性值
}
5.原型对象prototype:
(1)定义通用方法:
构造函数名.prototype.通用方法名 = function(){ //将通用方法定义在原型对象prototype中(和__proto__等价),new的不同对象都能使用此通用方法
...
}
(2)给原型对象赋值:
构造函数名.prototype = {//将对象赋值给原型对象prototype
constructor: 构造函数名, //将指向原型对象的构造函数重新指向原来的function 构造函数
...
}
(3)扩展内置对象的方法:
定义自定义方法:
方式1:
系统内置类.prototype.自定义方法名 = function(){ //给原型对象增加自定义方法
...
}
方式2(部分系统类不支持):
系统内置类.prototype = {
自定义方法名: function(){ //给原型对象增加自定义方法
...
}
}
调用自定义方法:
系统内置类对象.自定义方法名();
6.ES5版本的继承(通过构造函数或原型对象模拟实现):
(1)通过子构造函数调用call实现继承:
function 父构造函数名(参数1){
this.父属性名1 = 参数1;
...
}
function 子构造函数名(参数1){
父构造函数名.call(this, 参数1); //将子构造函数的this指向父构造函数,实现模拟继承后,可以使用父构造函数的属性与方法
...
}
(2)通过原型对象prototype实现继承:
子构造函数名.prototype = new 子父构造函数名(); //将子构造函数的原型对象prototype指向父构造函数实例,实现模拟继承后,可以使用父构造函数的属性与方法
子构造函数名.prototype.constructor = 子构造函数名; //将指向父构造函数改回指向子构造函数本身
(3)调用父构造函数的属性或方法:
var 子引用名 = new 子构造函数名(值1);
子引用名.父属性名1; //能直接使用父构造函数的属性
三、类(ES6新增):
1.定义类、构造函数、方法:
class 类名{ //定义类
constructor(参数1, 参数2){ //定义构造函数(不需要时可以不写),参数可以没有,也可以有多个
this.属性1 = 参数1; //创建属性,并赋值
this.属性2 = 参数2; //创建属性,并赋值
this.方法名(); //调用本实例的方法
}
方法名(参数1, 参数2){ //定义方法,参数可以没有,也可以有多个
...
}
}
2.创建类的对象:
var 变量名 = new 类名(值1, 值2);
3.继承类:
class 类 extends 父类 { //与Java类似,可以使用父类的属性与方法
constructor(参数1, 参数2){ //参数可以没有,也可以有多个
super(参数1, 参数2); //调用父类构造函数
}
...
}
四、系统API:
1.系统函数:
alert("提示内容"); //弹出提示框
console.log("输出内容"); //浏览器Console中日志打印
console.log(typeof 变量值); //输出变量类型
var 变量名 = prompt("提示内容"); //弹出输入框,并将输入值存入变量,类型为String
2.Object类:
var obj = new Object(); //创建Object实例
if(obj instanceof 类名) ... //判断对象是否属于某个类
Object.keys(obj); //获取对象所有属性名,返回属性名数组,ES5新增
Object.defineProperty(obj, "属性名", { //定义或修改对象属性,第三个参数为特性,ES5新增
value: 值 //属性值
writable: true, //是否可以重写,true或false
enumerable: true, //是否可以被遍历,true或false,值为false时调用Object.keys(obj)时数组中将没有此属性名
configurable: true //是否可删除或可修改特性,true或false
});
Object.assign(变量名,待拷贝对象); //浅拷贝,ES6新增方法,只拷贝对象一层,深层只拷贝引用,修改引用的拷贝值影响原值。
深拷贝,需要自已实现,拷贝对象所有层内容,修改拷贝值不会影响原值
3.Math类:
Math.random(); //产生0-1的随机小数,不含1
Math.max(数字1, 数字2); //取列表最大值
Math.min(数字1, 数字2); //取列表最小值
Math.abs(数字); //取绝对值
Math.floor(小数); //向下取整数
Math.ceil(小数); //向上取整数
Math.round(小数); //四舍五入
Math.PI; //圆周率, 3.1415
4.Date类:
var date = new Date(); //创建当前日期对象
var date = new Date(年数字, 月数字, 日数字); //创建指定时间的日期对象,会比填入的大
var date = new Date("2021-01-01 01:01:00"); //创建指定时间的日期对象
date.getFullYear(); //获取年
date.getMonth(); //获取月
date.getDate(); //获取日
date.getDay(); //获取周(周日为0-周六为6)
date.getHours(); //获取时
date.getMinutes(); //获取分
date.getSeconds(); //获取秒
date.getTime(); //获取毫秒
date.valueOf(); //获取毫秒
5.Array类(数组):
var arr = [元素1, 元素2]; //创建数组
var arr = new Array(长度数值); //创建数组
var arr = new Array(元素1, 元素2); //创建数组,初始化元素
arr.length; //获取数组长度
Array.isArray(arr); //判断是否数组
arr[下标数值] = 值; //给指定下标的元素赋值
arr.push(元素值1, 元素值2); //在第length位置添加N个元素,数组length增加
var item = arr[下标数值]; //获取指定下标的元素
var item = arr.pop(); //获取并删除数组最后一个元素,length减1
arr.unshift(元素值1, 元素值2); //在第0位置添加N个元素,原有元素下标往后移,数组length增加
var item = arr.shift(); //获取并删除数组第0个元素,length减1
arr.indexOf(元素值1); //查找指定元素第1次出现的位置,找到返回下标,没找到返回-1
arr.lastIndexOf(元素值1); //查找指定元素最后一次出现在的位置,找到返回下标,没找到返回-1
arr.reverse(); //将数组翻转过来,例:[1,2,0]变[0,2,1]
arr.sort(function(a, b){ //对数组冒泡排序
return a - b; //升序
//return b - a; //降序
});
arr.toString(); //将数组转成字符串,元素之间用逗号隔开
arr.join(); //将数组转成字符串,元素之间用逗号隔开
arr.join("任意分隔符"); //将数组转成字符串,元素之间用指定分隔符隔开
arr.concat(数组2, 数组3); //将多个数组合成一个,返回新数组
arr.slice(开始下标, 结束下标); //按下标截取数组,返回新数组
arr.splice(开始下标, 删除个数); //删除数组中指定的N个元素
arr.forEach(function(item, i, list){//遍历数组,list为数组本身,ES5新增
//...
});
arr.map(function(item, i, list){//遍历数组,list为数组本身,ES5新增
//...
});
var newArr = arr.filter(function(item, i, list){//遍历数组(返回符合条件的新数组),ES5新增
return 条件表达式; //筛选符合条件的item,为true时item存入新数组中,最后组成一个新数组
})
var hasExist = arr.some(function(item, i, list){//遍历数组(返回一个布尔值),ES5新增
return 条件表达式; //条件为true时,终止循环并返回true
})
var hasExist = arr.every(function(item, i, list){//遍历数组(返回一个布尔值),ES5新增
return 条件表达式; //条件为true时,终止循环并返回true
})
...arr; //ES6新增,...表示扩展运算符,取出数组列表
let arr3 = [...arr1, ...arr2]; //ES6新增,使用扩展运算符合并arr1与arr2数组
arr1.push(...arr2); /ES6新增,合并arr1与arr2数组
let arr = [...obj]; //ES6新增,将类数组或可遍历的对象等伪数组转为真正的数组
let arr = Array.from(obj); //ES6新增,将类数组或可遍历的对象等伪数组转为真正的数组,等同[...obj]
let arr = Array.from(obj, item => 新值表达式); //ES6新增同上,item为每个元素,箭头后为表达式,处理每个元素后放入数组
let 变量名 = arr.find((item, index) => 条件表达式); //ES6新增,查找符合条件的元素,并返回该元素
let 变量名 = arr.findIndex((item, index) => 条件表达式); //ES6新增,查找符合条件的第1个元素,并返回该元素
arr.includes(元素); //ES6新增,判断数组中是否包含指定元素,返回true或false
6.String类(字符串,创建后不可变,每次重新赋值都是新创建):
var str = "字符串"; //创建字符串
var str = new String("字符串"); //创建字符串
str.length; //字符串长度
str.indexOf("需要查找的字符串"); //查找指定字符串第1次出现的位置,找到返回下标,没找到返回-1
str.indexOf("需要查找的字符串", 下标); //从指定下标开始,查找指定字符串第1次出现的位置,找到返回下标,没找到返回-1
var x = str.charAt(下标); //返回指定下标的字符
var x = str[下标]; //返回指定下标的字符
var x = str.charCodeAt(下标); //返回指定下标字符的ASCII码
str.concat("字符串2", "字符串3"); //拼接多个字符串,和+效果一样
str.substr(开始下标, 截取长度); //从指定下标截取字符串
str.slice(开始下标, 结束下标+1); //截取字符串,第2参数下标所在的字符不取
str.substring(开始下标, 结束下标+1); //截取字符串,第2参数下标所在的字符不取
str.replace("查找的字符串", "替换的新字符串"); //替换字符串
var arr = str.split("分隔符"); //将字符串转为数组
str.toUpperCase(); //将所有字符转换为大写
str.toLowerCase(); //将所有字符转换为小写
str.trim(); //去除字符串两端的空格
let 变量名2 = `xxx${变量名1}xxx`; //ES6新增,模板字符串,使用${}符号填入变量值,`为键盘Tab键上面的符号
let 变量名 = `ab
cd`; //ES6新增,模板字符串,内容换行不用加任何符号
let 变量名 = `${函数名()}`; //ES6新增,模板字符串,使用${}符号调用函数
str.startsWith('值'); //ES6新增,是否以指定值开头
str.endsWith('值'); //ES6新增,是否以指定值结尾
str.repeat(重复次数); //将字符串重复N次,返回新字符串
7.RegExp正则表达式:
var 变量 = /表达式/; //创建正则表达式对象
var 变量 = new RegExp(/表达式/); //创建正则表达式对象
变量.test(值); //验证值是否符合,值可以是数字或字符串
8.Set类(ES6新增,数据结构,值不能重复):
const set = new Set(); //创建Set对象
const set = new Set([值1, 值2]); //创建Set对象,并以数组赋值,如果传入重复值时会只存一个
set.size; //获取列表个数
set.add(值); //添加值
set.delete(值); //删除指定值
set.has(值); //判断是否含指定值
set.clear(); //清除所有
set.forEach((value) => { //遍历Set列表
//value为每个值
});
set.forEach(value => 一行表达式); //遍历Set列表
9.其他:
得到键盘按键的数值:this.keyCode;
打开新网页:window.location="a.html";
返回:window.history.back();
获取form表单引用:window.document.表单名;
获取form表单请求的事件:window.document.表单名.action;
为事件设置链接:document.表单名.action="a.html";
提交:document.表单名.submit();
获取form表单的请求方法:
window.document.表单名.method;
获取所有form表单的集合中第一个表单:
window.document.forms[0];
得到该节点的名称:
节点.name;
节点.nodeName;
得到该节点的类型:
节点.type;
节点.nodeType;
得到该节点的值:
节点.value;
节点.nodeValue;
得到节点的该属性的节点:
节点.getAttributeNode("name");
得到节点的该属性值:
节点.getAttribute("name属性");
为该id注册一个变化事件,当值改变时激发:
document.getElementById("id").οnchange=function(){
代码;
}
判断是否有子节点:
hasChildNodes();
获取父节点:
子节点.parentNode;
替换子节点:
旧子节点父节点.replaceChild(新节点,旧子节点);
为节点增加属性
节点.setAttribute("属性名","值");
创建新节点:
document.createElement("节点名");
创建文本节点
document.createTextNode("文本字符串");
加入指定节点中成为其最后一个子节点:
父节点.appendChild(新节点);
将新节点插入到目标节点前面:
父节点.insertBefore(新节点,目标节点);
删除子带点:
父节点.removeChild(子节点);
鼠标双击事件:
节点.ondblclick
增加节点内容文本或子节点:
节点.innerHTML("文本或者子节点");
显示弹出窗口:
window.showModalDialog("新窗口页面的url",window,"窗口大小参数");
窗口大小参数:dialogHeight:10;dialogWidth:20;help:no
得到弹出窗口之前窗口的windows引用
windows.dialogArgunents;
显示新窗口:
window.open("新窗口页面的url","打开窗口的方式","设置窗口样子");
打开窗口的方式:_blank,_parent等;
设置窗口样子:
得到前一窗口的windows引用
window.opener;
10.在js中加载XML:
(1)IE浏览器下:
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.loadXML("文件名.xml");
(2)其他浏览器下:
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.loadXML("文件名.xml");