JavaScript
基础语法
js引用
- 标签
- 文件
js输出
- 页面
- 控制台
- 弹出窗口
数据类型
- typeof运算符
- 作用
- 返回值
- String
- 常见转义字符
- Number
- 数值范围
- 三个特殊数字
- Boolean
- Undifined
- 何时是这个
- Null
- typeof会返回什么
- 同上比较为true
强制类型转换
一般是指,将其它的数据类型转换为String、Number、Boolean
- 转为String
- toString
- null和undifined情况
- String()
- null和undifined情况
- “”拼接
- 任意类型皆可
- toString
- 转为Number
- Number
- String情况
- 布尔
- null
- undefined
- paresInt
- parseFloat
- Number
- 转为Boolean
- 何时true
- 何时false
运算符及其优先级
- 算术
- 关系
- 逻辑
- &&
- 短路
- 返回结果
- ||
- 短路
- 返回结果
- !
- 特点
- &&
- 比较
- ==
- !=
- ===
- !==
- 条件运算符
- 三元
- 逗号运算符
- 作用
- 优先级
语句
表达式和运算符等内容可以理解成是我们一 门语言中的单词,短语。而语句(statement)就是我们这个语言中一句一句完 整的话了。语句是一个程序的基本单位,JavaScript的程序就是由一条一条语句构成的,每一条语句使用;结尾
- 代码块
- 条件语句
- if…else
- if
- if else
- if elseif else
- switch…case
- default、break作用
- if…else
- 循环语句
- while
- do…while
- for
- 跳转控制
- break
- continue
函数
- 创建
- 函数对象
- 函数声明
- 函数表达式
- 调用
- 参数
- 形参实参不匹配情况
- 返回值
- 嵌套函数
- 嵌套函数只能在当前函数中可以访问
- 匿名函数
- 如何创建接受
- 立即执行函数
- (function(){})()
- 对象中的函数
作用域、数据类型梳理
变量的作用的范围
- 全局作用域
- 函数作用域
- 声明提前
- 变量
- 函数
- 声明式创建
- 表达式创建
- 基本数据类型
- 引用数据类型
- 堆栈理解
对象
除了字符串、数字、true、false、null和undefined之外,JavaScript中的值都是对象。
- 创建
- 访问属性
- .
- []
- 删除属性
- delete
- 遍历对象
- for…in
- 工厂方法创建对象
- 构造函数创建对象
- 原型
- prototype
- proto
- 原型链
- Object的toString方法
- in、hasOwnProperty()
- 作用、区别
- 对象继承
- 原型链继承
- 借用构造函数继承
- 组合继承*
- 垃圾回收
将不再使用的对象设置null即可
数组对象
- 创建
- 对象创建
- 字面量创建
- 属性
- constructor
- length
- 方法
- push()
- pop()
- unshift()
- shift()
- foreach()
- 回调函数
我们创建但是不由我们调用的,我们称为回调函数 - 三个参数含义
- 回调函数
- slice()
- 两个参数含义
- splice()
- 1、2、第三个以及后面参数的含义
- concat()
- 几个参数 个代表什么
- join()
- 参数含义
- reverse()
- sort()
- 排序规则
函数对象
- call()
注意:默认fun()函数调用,this指向的是window对象,你可以使用call()调用函数,在调用的时候传入一个对象,这个对象就是this所指向的对象,也就是说,可以自己指定this的指向,然后从第二个参数开始,实参将会依次传递
- apply()
- bind()
- argumrnts参数
在调用函数时,浏览器每次都会传递进两个隐含的参数:
函数的上下文对象: this
封装实参的对象: arguments- length属性
- callee属性
- this指向
解析器在调用函数每次都会向函数内部传递进一个隐含的参数,这个隐含的参数就是this,this指向的是一个对象,这个对象我们称为函数执行的上下文对象,根据函数的调用方式的不同,this会指向不同的对象- 函数形式调用
- 方法形式调用
- 构造函数形式调用
- 使用call和apply调用
Date
- 获取当前时间
- 获取指定时间的日期对象
- 常用方法
- date.getFullYear()
- date.getMonth()
- date.getDate()
- date.getHours()
- date.getMinutes()
- date.getSeconds()
- date.getMilliseconds()
- 获取总毫秒数
- date.valueOf()
- date.getTime()
Math
- Math.PI
- Math.floor()
- Math.ceil()
- Math.round()
- Math.abs()
- Math.max()/Math.min()
- Math.random()
console.log(Math.round(Math.random() 10)); //生成一个0-10之间的随机数
console.log(Math.round(Math.random() (10 - 1) + 1)); //生成一个1-10之间的随机数
String
包装类
String():可以将基本数据类型字符串转换为String对象
- 属性
- constructor
- length
- 方法
- charAt()
- charCodeAt()
- concat()
- indexof()
- lastIndexof()
- slice()
- substring()
- substr()
- split()
- toUpperCase()
- toLowerCase()
RegExp
- 创建
- 对象
- 字面量
- 方法
- split()
- search()
- match()
- replace()
- 正则量词
- 常见字符
| [ ]
[a-z]:任意小写字母
[A-Z]:任意大写字母
[A-z]:任意字母
[0-9]:任意数字
[a-zA-Z0-9]
[^a-zA-Z0-9]
[^a-z]:除了任意小写字母
[^A-Z]:除了任意大写字母
[^A-z]:除了任意字母
[^0-9]:除了任意数字
{n} :正好出现n次
{m,} :出现m次及以上
{m,n} :出现m-n次- :至少一个,相当于{1,}
- :0个或多个,相当于{0,}
? :0个或1个,相当于{0,1}
^
$
\w \W \d \D \s \S \b \B
数组对象
数组也是对象的一种,数组是一种用于表达有顺序关系的值的集合的语言结构,也就是同类数据元素的有序集合。
数组的存储性能比普通对象要好,在开发中我们经常使用数组来存储一些数据。但是在JavaScript中是支持数组可以是不同的元素,这跟JavaScript的弱类型有关,此处不用纠结,我们大多数时候都是相同类型元素的集合。数组内的各个值被称作元素,每一个元素都可以通过索引(下标)来快速读取,索引是从零开始的整数。
使用typeof检查一个数组对象时,会返回object。
3.1.2、创建数组
3.1.2.1、使用对象创建
- 同类型有序数组创建:
var arr = new Array();
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
arr[5] = 6;
arr[6] = 7;
arr[7] = 8;
arr[8] = 9;
- 不同类型有序数组创建:
var arr = new Array();
arr[0] = 1;
arr[1] = "2";
arr[2] = 3;
arr[3] = "4";
arr[4] = 5;
arr[5] = "6";
arr[6] = 7;
arr[7] = "8";
arr[8] = 9;
3.1.2.2、使用字面量创建
- 同类型有序数组创建:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
1
- 不同类型有序数组创建:
var arr = [1, "2", 3, "4", 5, "6", 7, "8", 9];
1
3.1.3、遍历数组
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
123
3.1.4、数组属性
constructor属性
演示:返回创建数组对象的原型函数
var arr = [1,2,3,4];
console.log(arr.constructor);
12
length属性
演示:设置或返回数组元素的个数
var arr = [1,2,3,4];
console.log(arr.length);
12
3.1.5、数组方法
push()方法
演示:该方法可以向数组的末尾添加一个或多个元素,并返回数组的新的长度
var arr = ["孙悟空", "猪八戒", "沙和尚"];
var result = arr.push("唐僧", "蜘蛛精", "白骨精", "玉兔精");
console.log(arr);
console.log(result);
1234
pop()方法
演示:该方法可以删除数组的最后一个元素,并将被删除的元素作为返回值返回
var arr = ["孙悟空", "猪八戒", "沙和尚"];
var result = arr.pop();
console.log(arr);
console.log(result);
1234
unshift()方法
演示:该方法向数组开头添加一个或多个元素,并返回新的数组长度
var arr = ["孙悟空", "猪八戒", "沙和尚"];
var result = arr.unshift("牛魔王", "二郎神");
console.log(arr);
console.log(result);
1234
shift()方法
演示:该方法可以删除数组的第一个元素,并将被删除的元素作为返回值返回
var arr = ["孙悟空", "猪八戒", "沙和尚"];
var result = arr.shift();
console.log(arr);
console.log(result);
1234
forEach()方法
演示:该方法可以用来遍历数组
forEach()方法需要一个函数作为参数,像这种函数,由我们创建但是不由我们调用的,我们称为回调函数。数组中有几个元素函数就会执行几次,每次执行时,浏览器会将遍历到的元素,以实参的形式传递进来,我们可以来定义形参,来读取这些内容,浏览器会在回调函数中传递三个参数:
- 第一个参数:就是当前正在遍历的元素
- 第二个参数:就是当前正在遍历的元素的索引
- 第三个参数:就是正在遍历的数组
注意:这个方法只支持IE8以上的浏览器,IE8及以下的浏览器均不支持该方法,所以如果需要兼容IE8,则不要使用forEach(),还是使用for循环来遍历数组。
var arr = ["孙悟空", "猪八戒", "沙和尚"];
arr.forEach(function (value, index, obj) {
console.log(value + " #### " + index + " #### " + obj);
});
1234
slice()方法
演示:该方法可以用来从数组提取指定元素,该方法不会改变元素数组,而是将截取到的元素封装到一个新数组中返回
参数:
- 第一个参数:截取开始的位置的索引,包含开始索引
- 第二个参数:截取结束的位置的索引,不包含结束索引,第二个参数可以省略不写,此时会截取从开始索引往后的所有元素
注意:索引可以传递一个负值,如果传递一个负值,则从后往前计算,-1代表倒数第一个,-2代表倒数第二个。
var arr = ["孙悟空", "猪八戒", "沙和尚", "唐僧", "白骨精"];
var result = arr.slice(1, 4);
console.log(result);
result = arr.slice(3);
console.log(result);
result = arr.slice(1, -2);
console.log(result);
1234567
splice()方法
演示:该方法可以用于删除数组中的指定元素,该方法会影响到原数组,会将指定元素从原数组中删除,并将被删除的元素作为返回值返回
参数:
- 第一个参数:表示开始位置的索引
- 第二个参数:表示要删除的元素数量
- 第三个参数及以后参数:可以传递一些新的元素,这些元素将会自动插入到开始位置索引前边
var arr = ["孙悟空", "猪八戒", "沙和尚", "唐僧", "白骨精"];
var result = arr.splice(3, 2);
console.log(arr);
console.log(result);
result = arr.splice(1, 0, "牛魔王", "铁扇公主", "红孩儿");
console.log(arr);
console.log(result);
1234567
concat()方法
演示:该方法可以连接两个或多个数组,并将新的数组返回,该方法不会对原数组产生影响
var arr = ["孙悟空", "猪八戒", "沙和尚"];
var arr2 = ["白骨精", "玉兔精", "蜘蛛精"];
var arr3 = ["二郎神", "太上老君", "玉皇大帝"];
var result = arr.concat(arr2, arr3, "牛魔王", "铁扇公主");
console.log(result);
12345
join()方法
演示:该方法可以将数组转换为一个字符串,该方法不会对原数组产生影响,而是将转换后的字符串作为结果返回,在join()中可以指定一个字符串作为参数,这个字符串将会成为数组中元素的连接符,如果不指定连接符,则默认使用,作为连接符
var arr = ["孙悟空", "猪八戒", "沙和尚"];
var result = arr.join("@-@");
console.log(result);
123
reverse()方法
演示:该方法用来反转数组(前边的去后边,后边的去前边),该方法会直接修改原数组
var arr = ["孙悟空", "猪八戒", "沙和尚"];
arr.reverse();
console.log(arr);
123
sort()方法
演示:该方法可以用来对数组中的元素进行排序,也会影响原数组,默认会按照Unicode编码进行排序
var arr = ["b", "c", "a"];
arr.sort();
console.log(arr);
123
注意:即使对于纯数字的数组,使用sort()排序时,也会按照Unicode编码来排序,所以对数字进排序时,可能会得到错误的结果。
var arr = [1, 3, 2, 11, 5, 6];
arr.sort();
console.log(arr);
123
我们可以自己来指定排序的规则,我们可以在sort()添加一个回调函数,来指定排序规则,回调函数中需要定义两个形参,浏览器将会分别使用数组中的元素作为实参去调用回调函数,使用哪个元素调用不确定,但是肯定的是在数组中a一定在b前边,浏览器会根据回调函数的返回值来决定元素的顺序,如下:
- 如果返回一个大于0的值,则元素会交换位置
- 如果返回一个小于0的值,则元素位置不变
- 如果返回一个等于0的值,则认为两个元素相等,也不交换位置
经过上边的规则,我们可以总结下:
- 如果需要升序排列,则返回 a-b
- 如果需要降序排列,则返回 b-a
var arr = [1, 3, 2, 11, 5, 6];
arr.sort(function (a, b) {
return a - b;
});
console.log(arr);
12345
函数对象
call()、apply()和bind()
call()和apply()这两个方法都是函数对象的方法,需要通过函数对象来调用,当对函数调用call()和apply()都会调用函数执行,在调用call()和apply()可以将一个对象指定为第一个参数,此时这个对象将会成为函数执行时的this,call()方法可以将实参在对象之后依次传递,apply()方法需要将实参封装到一个数组中统一传递,如下演示:
call()方法演示:
function fun(a, b) {
console.log("a = " + a);
console.log("b = " + b);
console.log("fun = " + this);
}
var obj = {
name: "obj",
sayName: function () {
console.log(this.name);
}
};
fun(2, 3);
console.log("===============");
fun.call(obj, 2, 3);
12345678910111213141516
注意:默认fun()函数调用,this指向的是window对象,你可以使用call()调用函数,在调用的时候传入一个对象,这个对象就是this所指向的对象,也就是说,可以自己指定this的指向,然后从第二个参数开始,实参将会依次传递
apply()方法演示:
function fun(a, b) {
console.log("a = " + a);
console.log("b = " + b);
console.log("fun = " + this);
}
var obj = {
name: "obj",
sayName: function () {
console.log(this.name);
}
};
fun(2, 3);
console.log("===============");
fun.apply(obj, [2, 3]);
注意:默认fun()函数调用,this指向的是window对象,你可以使用apply()调用函数,在调用的时候传入一个对象,这个对象就是this所指向的对象,也就是说,可以自己指定this的指向,然后从第二个参数开始,需要制定一个实参数组进行参数传递
bind方法
bind() 方法不会调用函数,但是能改变函数内部this 指向,返回的是原函数改变this之后产生的新函数
如果只是想改变 this 指向,并且不想调用这个函数的时候,可以使用bind
应用场景:不调用函数,但是还想改变this指向
var o = {
name: 'andy'
};
function fn(a, b) {
console.log(this);
console.log(a + b);
};
var f = fn.bind(o, 1, 2); //此处的f是bind返回的新函数
f();//调用新函数 this指向的是对象o 参数使用逗号隔开
his指向
- 以函数形式调用时,this永远都是window注意定时器里面的this指向window)
- 以方法的形式调用时,this是调用方法的对象
- 以构造函数的形式调用时,this是新创建的那个对象
- 使用call和apply调用时,this是传入的那个指定对象
arguments参数
length/callee
在调用函数时,浏览器每次都会传递进两个隐含的参数:
- 函数的上下文对象: this
- 封装实参的对象: arguments
this对象我们已经学习过了,那arguments对象是什么呢?
arguments是一个类数组对象,它也可以通过索引来操作数据,也可以获取长度,在调用函数时,我们所传递的实参都会在arguments中保存,比如:arguments.length 可以用来获取实参的长度,我们即使不定义形参,也可以通过arguments来使用实参,只不过比较麻烦,例如:
- arguments[0]:表示第一个实参
- arguments[1]:表示第二个实参
- …
它里边有一个属性叫做callee,这个属性对应一个函数对象,就是当前正在指向的函数的对象。
arguments对象演示:
function fun(a, b) {
// 通过下标获取第一个参数
console.log(arguments[0]);
// 通过下标获取第二个参数
console.log(arguments[1]);
// 获取实参的个数
console.log(arguments.length);
// 看看它的函数对象
console.log(arguments.callee);
console.log(arguments.callee == fun);
}
fun("Hello", "World");
12345678910111213
Date对象
在JavaScript中使用Date对象来表示一个时间,如果直接使用构造函数创建一个Date对象,则会封装为当前代码执行的时间。
使用Date实例化日期对象
- 获取当前时间必须实例化:
var now = new Date();
- 获取指定时间的日期对象
var future = new Date('2019/5/1');
常用方法
var date = new Date();
console.log(date);
console.log(date.getFullYear());//获取当前日期对象的年份(四位数字年份)
console.log(date.getMonth());//获取当前日期对象的月份(0 ~ 11)
console.log(date.getDate());//获取当前日期对象的日数(1 ~ 31)
console.log(date.getHours());//获取当前日期对象的小时(0 ~ 23)
console.log(date.getMinutes());//获取当前日期对象的分钟(0 ~ 59)
console.log(date.getSeconds());//获取当前日期对象的秒钟(0 ~ 59)
console.log(date.getMilliseconds());//获取当前日期对象的毫秒(0 ~ 999)
12345678910
更多方法: 参考网站
通过Date实例获取总毫米数
- 总毫秒数的含义
基于1970年1月1日(世界标准时间)起的毫秒数 - 获取总毫秒数
// 实例化Date对象
var now = new Date();
// 1. 用于获取对象的原始值
console.log(date.valueOf())
console.log(date.getTime())
// 2. 简单写可以这么做
var now = + new Date();
// 3. HTML5中提供的方法,有兼容性问题
var now = Date.now();
Math对象
Math和其它的对象不同,它不是一个构造函数,它属于一个工具类不用创建对象,它里边封装了数学运算相关的属性和方法。
属性、方法名 | 功能 |
---|---|
Math.PI | 圆周率 |
Math.floor() | 向下取整 |
Math.ceil() | 向上取整 |
Math.round() | 四舍五入版 就近取整 注意 -3.5 结果是 -3 |
Math.abs() | 绝对值 |
Math.max()/Math.min() | 求最大和最小值 |
Math.random() | 获取范围在[0,1)内的随机值 |
案例演示:
/*固定值*/
console.log("PI = " + Math.PI);
console.log("E = " + Math.E);
console.log("===============");
/*正数*/
console.log(Math.abs(1)); //可以用来计算一个数的绝对值
console.log(Math.ceil(1.1)); //可以对一个数进行向上取整,小数位只有有值就自动进1
console.log(Math.floor(1.99)); //可以对一个数进行向下取整,小数部分会被舍掉
console.log(Math.round(1.4)); //可以对一个数进行四舍五入取整
console.log("===============");
/*负数*/
console.log(Math.abs(-1)); //可以用来计算一个数的绝对值
console.log(Math.ceil(-1.1)); //可以对一个数进行向上取整,小数部分会被舍掉
console.log(Math.floor(-1.99)); //可以对一个数进行向下取整,小数位只有有值就自动进1
console.log(Math.round(-1.4)); //可以对一个数进行四舍五入取整
console.log("===============");
/*随机数*/
//Math.random():可以用来生成一个0-1之间的随机数
//生成一个0-x之间的随机数:Math.round(Math.random()*x)
//生成一个x-y之间的随机数:Math.round(Math.random()*(y-x)+x)
console.log(Math.round(Math.random() * 10)); //生成一个0-10之间的随机数
console.log(Math.round(Math.random() * (10 - 1) + 1)); //生成一个1-10之间的随机数
console.log("===============");
/*数学运算*/
console.log(Math.pow(12, 3)); //Math.pow(x,y):返回x的y次幂
console.log(Math.sqrt(4)); //Math.sqrt(x) :返回x的平方根
1234567891011121314151617181920212223242526
更多方法: 参考网站
String对象
概述
在JS中为我们提供了三个包装类,通过这三个包装类可以将基本数据类型的数据转换为对象
- String():可以将基本数据类型字符串转换为String对象
- Number():可以将基本数据类型的数字转换为Number对象
- Boolean():可以将基本数据类型的布尔值转换为Boolean对象
// 1. 生成临时变量,把简单类型包装为复杂数据类型var temp = new String(‘andy’);
// 2. 赋值给我们声明的字符变量str = temp;
// 3. 销毁临时变量temp = null;
但是注意:我们在实际应用中不会使用基本数据类型的对象,如果使用基本数据类型的对象,在做一些比较时可能会带来一些不可预期的结果,在这一章节中,我们重点介绍String()对象的属性和方法。
字符串属性
constructor属性
演示:返回创建字符串对象的原型函数
var str = "Hello,World!";
console.log(str.constructor);
12
length属性
演示:可以用来获取字符串的长度
var str = "Hello,World!";
console.log(str.length);
12
字符串方法
charAt()方法
演示:该方法可以根据索引获取指定位置的字符
var str = "Hello,World!";
console.log(str.charAt(1));
12
charCodeAt()方法
演示:该方法获取指定位置字符的字符编码(Unicode编码)
var str = "Hello,World!";
console.log(str.charCodeAt(1));
12
concat()方法
演示:该方法可以用来连接两个或多个字符串
var str = "Hello,World!";
console.log(str.concat("你好,", "世界!"));
12
indexof()方法
演示:该方法可以检索一个字符串中是否含有指定内容,如果字符串中含有该内容,则会返回其第一次出现的索引,如果没有找到指定的内容,则返回-1,可以指定一个第二个参数,指定开始查找的位置
var str = "Hello,World!";
console.log(str.indexOf("o"));
console.log(str.indexOf("o", 5));
123
lastIndexOf()方法
演示:该方法的用法和indexOf()一样,不同的是indexOf是从前往后找,而lastIndexOf是从后往前找,也可以指定开始查找的位置
var str = "Hello,World!";
console.log(str.lastIndexOf("o"));
console.log(str.lastIndexOf("o", 5));
123
slice()方法
演示:可以从字符串中截取指定的内容,不会影响原字符串,而是将截取到内容返回
参数:
- 第一个参数:开始位置的索引(包括开始位置)
- 第二个参数:结束位置的索引(不包括结束位置),如果省略第二个参数,则会截取到后边所有的
注意:也可以传递一个负数作为参数,负数的话将会从后边计算
var str = "Hello,World!";
var result = str.slice(1, 4);
console.log(result);
result = str.slice(1);
console.log(result);
result = str.slice(1, -1);
console.log(result);
1234567
substring()方法
演示:可以用来截取一个字符串,它和slice()类似
参数:
- 第一个参数:开始截取位置的索引(包括开始位置)
- 第二个参数:结束位置的索引(不包括结束位置),如果省略第二个参数,则会截取到后边所有的
注意:不同的是这个方法不能接受负值作为参数,如果传递了一个负值,则默认使用0,而且它还自动调整参数的位置,如果第二个参数小于第一个,则自动交换
var str = "Hello,World!";
var result = str.substring(1, 4);
console.log(result);
result = str.substring(1);
console.log(result);
result = str.substring(1, -1);
console.log(result);
1234567
substr()方法
演示:该方法用来截取字符串
参数:
- 第一个参数:截取开始位置的索引
- 第二个参数:截取的长度
var str = "Hello,World!";
var result = str.substr(6, 6);
console.log(result);
123
split()方法
演示:该方法可以将一个字符串拆分为一个数组,需要一个字符串作为参数,将会根据该字符串去拆分数组
var str = "Hello,World!";
var result = str.split(",");
console.log(result);
123
toUpperCase()方法
演示:将一个字符串转换为大写并返回
var str = "Hello,World!";
var result = str.toUpperCase();
console.log(result);
123
toLowerCase()方法
演示:将一个字符串转换为小写并返回
var str = "Hello,World!";
var result = str.toLowerCase();
console.log(result);
123
DOM
文档对象模型(Document Object Model)
将网页中的每一个部分都转换成为了对象
模型:用来表示对象与对象之前的关系
节点
- 文档节点:整个HTML文档 ``` 文档节点(Document)代表的是整个HTML文 档,网页中的所有节点都是它的子节点。
document对象作为window对象的属性存在的,我们不用获取可以直接使用。
通过该对象我们可以在整个文档访问内查找节点对象,并可以通过该对象创建各种节点对象。
- 元素节点:HTML文档中的HTML标签
HTML中的各种标签都是元素节点(Element),这也是我们最常用的一个节点。
浏览器会将页面中所有的标签都转换为一个元素节点, 我们可以通过document的方法来获取元素节点。
例如:document.getElementById()
,根据id属性值获取一个元素节点对象。
console.dir() 打印我们返回的元素对象 更好的查看里面的属性和方法
- 属性节点:元素的属性
属性节点(Attribute)表示的是标签中的一个一个的属 性,这里要注意的是属性节点并非是元素节点的子节点,而是元素节点的一部分。可以通过元素节点来获取指定的属性节点。
注意:我们一般不使用属性节点。
- 文本节点:HTML标签中的文本内容
文本节点(Text)表示的是HTML标签以外的文本内容,任意非HTML的文本都是文本节点,它包括可以字面解释的纯文本内容。文本节点一般是作为元素节点的子节点存在的。获取文本节点时,一般先要获取元素节点,在通过元素节点获取文本节点
<a name="16c343da"></a>
### 节点属性
> 想象成表格
![](JavaScript.assets/2271dc3f0f61e890fe4cb76817fc6942.png#crop=0&crop=0&crop=1&crop=1&id=Mkl0Q&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
<a name="2b6bc0f2"></a>
## 操作
<a name="8ace326e"></a>
### 查找html元素
| 方法 | 描述 |
| --- | --- |
| document.getElementById(_id_) | 通过元素 id 来查找元素。 |
| document.getElementsByTagName(_name_) | 通过标签名来查找元素。 |
| document.getElementsByClassName(_name_) | 通过类名来查找元素。 |
| document.querySelector(_CSS选择器_) | 通过CSS选择器选择一个元素。 |
| document.querySelectorAll(_CSS选择器_) | 通过CSS选择器选择多个元素。 |
<a name="b666c515"></a>
### 获取html元素值
| 方法 | 描述 |
| --- | --- |
| **元素节点.innerText** | 获取 HTML 元素的 inner Text。 |
| **元素节点.innerHTML** | 获取 HTML 元素的 inner HTML。 |
| **元素节点.属性** | 获取 HTML 元素的属性值。 |
| **元素节点.getAttribute(_attribute_)** | 获取 HTML 元素的属性值。 |
| **元素节点.style.样式** | 获取 HTML 元素的行内样式值。 |
<a name="b19e5c3a"></a>
### 改变html元素值
| 方法 | 描述 |
| --- | --- |
| **元素节点.innerText = _new text content_** | 改变元素的 inner Text。 |
| **元素节点.innerHTML = _new html content_** | 改变元素的 inner HTML。 |
| **元素节点.属性 = _new value_** | 改变 HTML 元素的属性值。 |
| **元素节点.setAttribute(attribute, value)** | 改变 HTML 元素的属性值。**改变单独的css文件里的样式** |
| **元素节点.style.样式 = new style** | 改变 HTML 元素的行内样式值。 |
<a name="969c078a"></a>
### 增、改html元素节点
| 方法 | 描述 |
| --- | --- |
| **document.createElement(_element_)** | 创建 HTML 元素节点。 |
| **document.createAttribute(_attribute_)** | 创建 HTML 属性节点。 |
| **document.createTextNode(_text_)** | 创建 HTML 文本节点。 |
| **元素节点.removeChild(_element_)** | 删除 HTML 元素。 |
| **元素节点.appendChild(_element_)** | 添加 HTML 元素。 |
| **元素节点.replaceChild(_element_)** | 替换 HTML 元素。 |
| **元素节点.insertBefore(_element_)** | 在指定的子节点前面插入新的子节点。 |
| **removeAttribute** | 移除属性 |
<a name="16faa692"></a>
### 查找父子/兄弟
| 方法 | 描述 |
| --- | --- |
| **元素节点.parentNode** | 返回元素的父节点。 |
| **元素节点.parentElement** | 返回元素的父元素。 |
| **元素节点.childNodes** | 返回元素的一个子节点的数组(包含空白文本Text节点)。 |
| **元素节点.children** | 返回元素的一个子元素的集合(不包含空白文本Text节点)。 |
| **元素节点.firstChild** | 返回元素的第一个子节点(包含空白文本Text节点)。 |
| **元素节点.firstElementChild** | 返回元素的第一个子元素(不包含空白文本Text节点)。 |
| **元素节点.lastChild** | 返回元素的最后一个子节点(包含空白文本Text节点)。 |
| **元素节点.lastElementChild** | 返回元素的最后一个子元素(不包含空白文本Text节点)。 |
| **元素节点.previousSibling** | 返回某个元素紧接之前节点(包含空白文本Text节点)。 |
| **元素节点.previousElementSibling** | 返回指定元素的前一个兄弟元素(相同节点树层中的前一个元素节点)。 |
| **元素节点.nextSibling** | 返回某个元素紧接之后节点(包含空白文本Text节点)。 |
| **元素节点.nextElementSibling** | 返回指定元素的后一个兄弟元素(相同节点树层中的下一个元素节点)。 |
<a name="5dfd30da"></a>
## 事件(常用)
> 用户和浏览器之间的交互行为,eg:点击按钮、鼠标移动、拖动窗口……
>
> HTML DOM 事件允许 JavaScript 在 HTML 文档中的元素上注册不同的事件处理程序。事件通常与函数结合使用,在事件发生之前函数不会被执行(例如当用户单击按钮时)
**文档加载**
浏览器自上向下加载,读取一行运行一行,script要写在下面,否则代码执行时页面还没加载
**执行步骤**
1、获取事件源<br />2、注册事件(也叫绑定事件,绑定给对象)<br />3、添加事件处理程序( 一般用function函数)
**DOM:** 指明使用的 DOM 属性级别。
<a name="d872400c"></a>
### 鼠标事件
| 属性 | 描述 | DOM |
| --- | --- | --- |
| [onclick](https://www.runoob.com/jsref/event-onclick.html) | 当用户点击某个对象时调用的事件句柄。 | 2 |
| [oncontextmenu](https://www.runoob.com/jsref/event-oncontextmenu.html) | 在用户点击鼠标右键打开上下文菜单时触发 | |
| [ondblclick](https://www.runoob.com/jsref/event-ondblclick.html) | 当用户双击某个对象时调用的事件句柄。 | 2 |
| [onmousedown](https://www.runoob.com/jsref/event-onmousedown.html) | 鼠标按钮被按下。 | 2 |
| [onmouseenter](https://www.runoob.com/jsref/event-onmouseenter.html) | 当鼠标指针移动到元素上时触发。 | 2 |
| [onmouseleave](https://www.runoob.com/jsref/event-onmouseleave.html) | 当鼠标指针移出元素时触发 | 2 |
| [onmousemove](https://www.runoob.com/jsref/event-onmousemove.html) | 鼠标被移动。 | 2 |
| [onmouseover](https://www.runoob.com/jsref/event-onmouseover.html) | 鼠标移到某元素之上。 | 2 |
| [onmouseout](https://www.runoob.com/jsref/event-onmouseout.html) | 鼠标从某元素移开。 | 2 |
| [onmouseup](https://www.runoob.com/jsref/event-onmouseup.html) | 鼠标按键被松开。 | 2 |
<a name="f148ff2a"></a>
### 窗口事件
由窗口触发该事件 (**同样适用于 body 标签**):
| 属性 | 描述 |
| --- | --- |
| **onblur** | 当窗口失去焦点时运行脚本。 |
| **onfocus** | 当窗口获得焦点时运行脚本。 |
| **onload** | 当文档加载之后运行脚本。 |
| **onresize** | 当调整窗口大小时运行脚本。 |
| **onstorage** | 当 Web Storage 区域更新时(存储空间中的数据发生变化时)运行脚本。 |
<a name="32f13c9d"></a>
### 键盘事件
| 属性 | 描述 | DOM |
| --- | --- | --- |
| [onkeydown](https://www.runoob.com/jsref/event-onkeydown.html) | 某个键盘按键被按下。 | 2 |
| [onkeypress](https://www.runoob.com/jsref/event-onkeypress.html) | 某个键盘按键被按下并松开。 | 2 |
| [onkeyup](https://www.runoob.com/jsref/event-onkeyup.html) | 某个键盘按键被松开。 | 2 |
<a name="da8da71e"></a>
### 表单事件
| 属性 | 描述 | DOM |
| --- | --- | --- |
| [onblur](https://www.runoob.com/jsref/event-onblur.html) | 元素失去焦点时触发 | 2 |
| [onchange](https://www.runoob.com/jsref/event-onchange.html) | 该事件在表单元素的内容改变时触发( , , , 和 | 2 |
| [onfocus](https://www.runoob.com/jsref/event-onfocus.html) | 元素获取焦点时触发 | 2 |
| [onfocusin](https://www.runoob.com/jsref/event-onfocusin.html) | 元素即将获取焦点时触发 | 2 |
| [onfocusout](https://www.runoob.com/jsref/event-onfocusout.html) | 元素即将失去焦点时触发 | 2 |
| [oninput](https://www.runoob.com/jsref/event-oninput.html) | 元素获取用户输入时触发 | 3 |
| [onreset](https://www.runoob.com/jsref/event-onreset.html) | 表单重置时触发 | 2 |
| [onsearch](https://www.runoob.com/jsref/event-onsearch.html) | 用户向搜索域输入文本时触发 ( <input="search">) | |
| [onselect](https://www.runoob.com/jsref/event-onselect.html) | 用户选取文本时触发 ( 和 | 2 |
| [onsubmit](https://www.runoob.com/jsref/event-onsubmit.html) | 表单提交时触发 | 2 |
<a name="eea1cc26"></a>
### 媒体事件
> 详细见菜鸟文档
| 事件 | 描述 |
| --- | --- |
| [onabort](https://www.runoob.com/jsref/event-onabort-media.html) | 事件在视频/音频(audio/video)终止加载时触发。 |
| [onended](https://www.runoob.com/jsref/event-onended.html) | 事件在视频/音频(audio/video)播放结束时触发。 |
<a name="a3d39107"></a>
### 拖动事件
| 事件 | 描述 |
| --- | --- |
| [ondrag](https://www.runoob.com/jsref/event-ondrag.html) | 该事件在元素正在拖动时触发 |
| [ondragend](https://www.runoob.com/jsref/event-ondragend.html) | 该事件在用户完成元素的拖动时触发 |
| [ondragenter](https://www.runoob.com/jsref/event-ondragenter.html) | 该事件在拖动的元素进入放置目标时触发 |
| [ondragleave](https://www.runoob.com/jsref/event-ondragleave.html) | 该事件在拖动元素离开放置目标时触发 |
| [ondragover](https://www.runoob.com/jsref/event-ondragover.html) | 该事件在拖动元素在放置目标上时触发 |
| [ondragstart](https://www.runoob.com/jsref/event-ondragstart.html) | 该事件在用户开始拖动元素时触发 |
| [ondrop](https://www.runoob.com/jsref/event-ondrop.html) | 该事件在拖动元素放置在目标区域时触发 |
<a name="4ef87725"></a>
### 鼠标/键盘事件对象
<a name="24d67862"></a>
#### 属性
| 属性 | 描述 | DOM |
| --- | --- | --- |
| [altKey](https://www.runoob.com/jsref/event-altkey.html) | 返回当事件被触发时,"ALT" 是否被按下。 | 2 |
| [button](https://www.runoob.com/jsref/event-button.html) | 返回当事件被触发时,哪个鼠标按钮被点击。 | 2 |
| [clientX](https://www.runoob.com/jsref/event-clientx.html) | 返回当事件被触发时,鼠标指针的水平坐标。 | 2 |
| [clientY](https://www.runoob.com/jsref/event-clienty.html) | 返回当事件被触发时,鼠标指针的垂直坐标。 | 2 |
| [ctrlKey](https://www.runoob.com/jsref/event-ctrlkey.html) | 返回当事件被触发时,"CTRL" 键是否被按下。 | 2 |
| [Location](https://www.runoob.com/jsref/event-key-location.html) | 返回按键在设备上的位置 | 3 |
| [charCode](https://www.runoob.com/jsref/event-key-charcode.html) | 返回onkeypress事件触发键值的字母代码。 | 2 |
| [key](https://www.runoob.com/jsref/event-key-key.html) | 在按下按键时返回按键的标识符。 | 3 |
| [keyCode](https://www.runoob.com/jsref/event-key-keycode.html) | 返回onkeypress事件触发的键的值的字符代码,或者 onkeydown 或 onkeyup 事件的键的代码。 | 2 |
| [which](https://www.runoob.com/jsref/event-key-which.html) | 返回onkeypress事件触发的键的值的字符代码,或者 onkeydown 或 onkeyup 事件的键的代码。 | 2 |
| [metaKey](https://www.runoob.com/jsref/event-metakey.html) | 返回当事件被触发时,"meta" 键是否被按下。 | 2 |
| [relatedTarget](https://www.runoob.com/jsref/event-relatedtarget.html) | 返回与事件的目标节点相关的节点。 | 2 |
| [screenX](https://www.runoob.com/jsref/event-screenx.html) | 返回当某个事件被触发时,鼠标指针的水平坐标。 | 2 |
| [screenY](https://www.runoob.com/jsref/event-screeny.html) | 返回当某个事件被触发时,鼠标指针的垂直坐标。 | 2 |
| [shiftKey](https://www.runoob.com/jsref/event-shiftkey.html) | 返回当事件被触发时,"SHIFT" 键是否被按下。 | 2 |
<a name="1804dc50"></a>
### 动画事件
| 事件 | 描述 |
| --- | --- |
| [animationend](https://www.runoob.com/jsref/event-animationend.html) | 该事件在 CSS 动画结束播放时触发 |
| [animationiteration](https://www.runoob.com/jsref/event-animationiteration.html) | 该事件在 CSS 动画重复播放时触发 |
| [animationstart](https://www.runoob.com/jsref/event-animationstart.html) | 该事件在 CSS 动画开始播放时触发 |
<a name="5b66b4e7"></a>
### 过渡事件
| 事件 | 描述 |
| --- | --- |
| [transitionend](https://www.runoob.com/jsref/event-transitionend.html) | 该事件在 CSS 完成过渡后触发。 |
<a name="1bb99a7a"></a>
## 事件注册、监听
<a name="fe0e8bf7"></a>
### 注册
![](JavaScript.assets/1551165252019.png#crop=0&crop=0&crop=1&crop=1&id=OSEo4&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
<a name="bf0d2ab9"></a>
## 事件冒泡
> 所谓的冒泡指的就是事件的向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发,在开发中大部分情况冒泡都是有用的,如果不希望发生事件冒泡可以通过事件对象来取消冒泡。
<a name="ec4a572b"></a>
### 阻止事件冒泡
<a name="f7951853"></a>
### 阻止默认行为
<a name="e814d24d"></a>
## 事件委派
> 事件的委派,是指将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。事件委派是利用了事件冒泡,通过委派可以减少事件绑定的次数,提高程序的性能。
<a name="edfbb65b"></a>
## 事件绑定
我们以前绑定事件代码只能一个事件绑定一个函数,现在要一个事件对应多个函数
事件绑定和事件解绑的兼容性代码
```javascript
/*为元素绑定事件兼容性代码*/
function addEventListener(element, type, fn) {
if(element.addEventListener) {
element.addEventListener(type, fn, false);
} else if(element.attachEvent) {
element.attachEvent("on" + type, fn);
} else {
element["on" + type] = fn;
}
}
/*为元素解绑事件兼容性代码*/
function removeEventListener(element, type, fnName) {
if(element.removeEventListener) {
element.removeEventListener(type, fnName, false);
} else if(element.detachEvent) {
element.detachEvent("on" + type, fnName);
} else {
element["on" + type] = null;
}
}
事件传播
- 捕获阶段:在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件
- 目标阶段:事件捕获到目标元素,捕获结束开始在目标元素上触发事件
- 冒泡阶段:事件从目标元素向它的祖先元素传递,依次触发祖先元素上的事件
BOM
Window对象
- 弹出框
- 警告
- 确认
- 提示
- 定时事件
- 延时器
- 定时器
- 常用窗口方法
- window.open()
- window.close()
- 调整窗口大小事件window.onresize
Navigator对象
Location对象
console.log(location); //输出location对象
console.log(location.href); //输出当前地址的全路径地址
console.log(location.origin); //输出当前地址的来源
console.log(location.protocol); //输出当前地址的协议
console.log(location.hostname); //输出当前地址的主机名
console.log(location.host); //输出当前地址的主机
console.log(location.port); //输出当前地址的端口号
console.log(location.pathname); //输出当前地址的路径部分
console.log(location.search); //输出当前地址的?后边的参
- 常用方法
- assign()
- reload()
- replace()
History对象
- 属性
- 方法
- back()
- forward()
- go()
Screen对象
- 属性
| 属性 | 描述 | | —- | —- | | availHeight | 返回显示屏幕的高度 (除 Windows 任务栏之外)。 | | availWidth | 返回显示屏幕的宽度 (除 Windows 任务栏之外)。 | | bufferDepth | 设置或返回调色板的比特深度。 | | colorDepth | 返回目标设备或缓冲器上的调色板的比特深度。 | | deviceXDPI | 返回显示屏幕的每英寸水平点数。 | | deviceYDPI | 返回显示屏幕的每英寸垂直点数。 | | fontSmoothingEnabled | 返回用户是否在显示控制面板中启用了字体平滑。 | | height | 返回显示屏幕的高度。 | | logicalXDPI | 返回显示屏幕每英寸的水平方向的常规点数。 | | logicalYDPI | 返回显示屏幕每英寸的垂直方向的常规点数。 | | pixelDepth | 返回显示屏幕的颜色分辨率(比特每像素)。 | | updateInterval | 设置或返回屏幕的刷新率。 | | width | 返回显示器屏幕的宽度。 |
Js执行机制
- 单线程
- 同步、异步
- 执行机制
元素系列
- 元素偏移量offset
- 元素可视区client
- 元素滚动scrool
移动端特效
1. 触屏事件
2. 触屏touch事件
2. 触摸事件对象(TouchEvent)
3. 移动端拖动元素
案例:移动端拖动元素
4. 案例: 移动轮播图
5. classList 属性
- 5.1. 案例分析
- 5.2. 案例:返回顶部
- 5.2.1. 案例分析
6. click 延时解决方案
7. 移动端常用开发插件
- 7.1. 什么是插件
- 7.2. 插件的使用
- 7.3. Swiper 插件的使用
- 7.4. 其他移动端常见插件
- 7.5. 插件的使用总结
- 7.6. 移动端视频插件 zy.media.js
8. 移动端常用开发框架
- 8.1. 移动端视频插件 zy.media.js
- 8.2. Bootstrap
PC端特效
1. 动画函数封装
- 1.1. 动画实现原理
- 1.2. 动画函数给不同元素记录不同定时器
- 1.3. 缓动效果原理
- 1.4. 动画函数多个目标值之间移动
- 1.3. 动函数添加回调函数
- 1.4. 动画完整版代码:
2. 常见网页特效案例
- 2.1. 案例:网页轮播图
- 2.2. 节流阀
- 2.3. 案例:返回顶部
- 2.4. 案例:筋头云案例
高级语法
Exception
Error对象
- 属性
- name
- message
- name属性值
- EvalError
- RangeError
- ReferenceError
- SyntaxError
- TypeError
- URIError
异常捕捉
ES3开始引入了 try-catch 语句,是 JavaScript 中处理异常的标准方式。
语法格式:
try {
// 可能发生异常的代码
} catch (error) {
// 发生错误执行的代码
} finally {
// 无论是否出错都会执行的代码
}
在 try…catch 中,try 中一旦出现错误则其它语句不能执行,如果不出现错误则 catch 中的语句不会执行。
Javascript 参考其它编程语言,也提供了一种 finally 语句:不管 try 中的语句有没有错误,在最后都会执行 finally 中的语句。也就是说,try 中语句不发生错误执行完毕后会执行 finally 中的语句,try 中的语句发生错误,则执行 catch中的语句,catch 中的语句执行完毕后也会执行 finally 中的语句。
案例演示:
try {
console.log(a);
console.log("a未定义肯定报错,你看不见我");
} catch (error) {
// 发生错误执行的代码
console.log(error);
} finally {
// 无论是否出错都会执行的代码
console.log("finally 执行了 ...")
}
在JavaScript中,如果添加了 finally 语句,则 catch 语句可以省略。但是如果没有 catch 语句,则一旦发生错误就无法捕获这个错误,所以在执行完 finally 中的语句后,程序就会立即停止了。所以,在实际使用中,最好一直带着 catch 语句。如果你写了 catch 语句,则finally 语句也是可以省略的。
异常演示
Eval 错误
EvalError 指示 eval() 函数中的错误。更新版本的 JavaScript 不会抛出任何 EvalError,请使用 SyntaxError 代替。
案例演示:
try {
eval("alert('Hello)"); // 缺少 ' 会产生错误
} catch (error) {
console.log(error)
}
范围错误
RangeError 会在您使用了合法值的范围之外的数字时抛出。
案例演示:您不能将数字的有效位数设置为 500。
var num = 1;
try {
num.toPrecision(500); // 数无法拥有 500 个有效数
} catch (error) {
console.log(error)
}
引用错误
假如您使用(引用)了尚未声明的变量,则 ReferenceError 会被抛出:
案例演示:
var x;
try {
x = y + 1; // y 无法被引用(使用)
} catch (error) {
console.log(error)
}
语法错误
假如您计算带语法错误的代码,会 SyntaxError 被抛出:
案例演示:
try {
eval("alert('Hello)"); // 缺少 ' 会产生错误
} catch (error) {
console.log(error)
}
12345
类型错误
假如您使用的值不在期望值的范围之内,则 TypeError 被抛出:
案例演示:
var num = 1;
try {
num.toUpperCase(); // 您无法将数字转换为大写
} catch (error) {
console.log(error)
}
123456
URI 错误
假如您在 URI 函数中使用非法字符,则 URIError 被抛出:
案例演示:
try {
decodeURI("%%%"); // 您无法对这些百分号进行 URI 编码
} catch (error) {
console.log(error)
}
12345
异常抛出
在大部分的代码执行过程中,都是出现错误的时候,由浏览器(javascript引擎)抛出异常,然后程序或者停止执行或被try…catch 捕获。
然而有时候我们在检测到一些不合理的情况发生的时候也可以主动抛出错误,请使用 throw 关键字抛出来主动抛出异常。
注意事项:
- thow后面就是我们要抛出的异常对象,在以前的时候都是出现错误的时候浏览器抛出异常对象,只是现在是我们自己主动抛出的异常对象。
- 只要有异常对象抛出,不管是浏览器抛出的,还是代码主动抛出,都会让程序停止执行。如果想让程序继续执行,则有也可以用try…catch来捕获。
- 每一个错误类型都可以传入一个参数,表示实际的错误信息。
- 我们可以在适当的时候抛出任何我们想抛出的异常类型。
throw new SyntaxError("语法错误...");
主动抛出内置异常
/*该函数接收一个数字,返回它的平方。*/
function foo(num) {
if (typeof num == "number") {
return num * num;
} else {
throw new TypeError("您输入的是一个非法数字!")
}
}
console.log(foo(4));
console.log(foo("abc"));
1234567891011
主动抛出自定义异常
我们不仅仅可以抛出js内置的错误类型的对象,也可以自定义错误类型,然后抛出自定义错误类型的对象。
如果要自定义错误类型,只需要继承任何一个自定义错误类型都可以,一般直接继承Error即可。
/*自定义错误*/
function MyError(message) {
this.message = "注意:这是自定义的错误"
this.name = "自定义错误";
}
MyError.prototype = new Error();
try {
throw new MyError("注意:这是自定义错误类型")
} catch (error) {
console.log(error.message)
}
Json
- 数据类型
- 字符串
JSON 中的字符串必须用双引号包围。
- 字符串
- 数字
JSON 中的数字必须是整数或浮点数。
- 对象
JSON 中的值可以是对象,JSON 中作为值的对象必须遵守与 JSON 对象相同的规则。
{
"employee": {"name": "Bill Gates", "age": 62, "city": "Seattle"}
}
- 布尔
- null
- 不可以是
- 函数
- 日期
- undefined
- 与对象的转换
- JSON.parse()
- JSON.stringify()
Ajax
AJAX的XMLHttpRequest对象
AJAX 的核心是 XMLHttpRequest 对象。 所有现代浏览器都支持 XMLHttpRequest 对象。
XMLHttpRequest 对象用于幕后同服务器交换数据,这意味着可以更新网页的部分,而不需要重新加载整个页面。
所有现代浏览器(Chrom、IE7+、Firefox、Safari 以及 Opera)都有内建的 XMLHttpRequest 对象。
创建 XMLHttpRequest 的语法是:
variable = new XMLHttpRequest();
老版本的 Internet Explorer(IE5 和 IE6)使用 ActiveX 对象:
variable = new ActiveXObject("Microsoft.XMLHTTP");
为了应对所有浏览器,包括 IE5 和 IE6,请检查浏览器是否支持 XMLHttpRequest 对象。如果支持,创建 XMLHttpRequest 对象,如果不支持,则创建 ActiveX 对象:
var xhttp;
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
但是需要注意的是,出于安全原因,现代浏览器不允许跨域访问,这意味着尝试加载的网页和 XML 文件都必须位于相同服务器上。
6.3.3、AJAX的XMLHttpRequest对象方法
方法 | 描述 |
---|---|
new XMLHttpRequest() | 创建新的 XMLHttpRequest 对象 |
abort() | 取消当前请求 |
getAllResponseHeaders() | 返回头部信息 |
getResponseHeader() | 返回特定的头部信息 |
open(method, url, async, user, psw) | 规定请求method:请求类型 GET 或 POST url:文件位置 async:true(异步)或 false(同步) user:可选的用户名称 psw:可选的密码 |
send() | 将请求发送到服务器,用于 GET 请求 |
send(string) | 将请求发送到服务器,用于 POST 请求 |
setRequestHeader() | 向要发送的报头添加标签/值对 |
6.3.4、AJAX的XMLHttpRequest对象属性
属性 | 描述 |
---|---|
onreadystatechange | 定义当 readyState 属性发生变化时被调用的函数 |
readyState | 保存 XMLHttpRequest 的状态。 0:请求未初始化 1:服务器连接已建立 2:请求已收到 3:正在处理请求 4:请求已完成且响应已就绪 |
responseText | 以字符串返回响应数据 |
responseXML | 以 XML 数据返回响应数据 |
status | 返回请求的状态号 200: “OK” 403: “Forbidden” 404: “Not Found” 如需完整列表请访问 Http 消息参考手册 |
statusText | 返回状态文本(比如 “OK” 或 “Not Found”) |
6.3.5、AJAX的GET请求
工程结构:
users.json
[
{"name":"孙悟空","age":18,"gender":"男"},
{"name":"猪八戒","age":19,"gender":"男"},
{"name":"唐僧","age":20,"gender":"男"},
{"name":"沙和尚","age":21,"gender":"男"}
]
index.html
//步骤一:创建异步对象
var ajax = new XMLHttpRequest();
//步骤二:设置请求的url参数,参数一是请求的类型,参数二是请求的url
ajax.open("get", "users.json");
//步骤三:发送请求
ajax.send();
//步骤四:注册事件 onreadystatechange 状态改变就会调用
ajax.onreadystatechange = function () {
if (ajax.readyState == 4 && ajax.status == 200) {
//步骤五:如果能够进到这个判断,说明数据完美的回来了,并且请求的页面是存在的
console.log(ajax.responseText);//输入响应的内容
}
};
控制台:
6.3.6、AJAX的POST请求
工程结构:
users.json
[
{"name":"孙悟空","age":18,"gender":"男"},
{"name":"猪八戒","age":19,"gender":"男"},
{"name":"唐僧","age":20,"gender":"男"},
{"name":"沙和尚","age":21,"gender":"男"}
]
index.html
//步骤一:创建异步对象
var ajax = new XMLHttpRequest();
//步骤二:设置请求的类型及url,注意:post请求一定要添加请求头才行不然会报错
ajax.open("post", "users.json");
ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//步骤三:发送请求
ajax.send();
//步骤四:注册事件 onreadystatechange 状态改变就会调用
ajax.onreadystatechange = function () {
//步骤五:如果能够进到这个判断,说明数据完美的回来了,并且请求的页面是存在的
if (ajax.readyState == 4 && ajax.status == 200) {
console.log(ajax.responseText);//输入响应的内容
}
};
控制台:
6.3.7、AJAX的请求整合
工程结构:
users.json
[
{"name":"孙悟空","age":18,"gender":"男"},
{"name":"猪八戒","age":19,"gender":"男"},
{"name":"唐僧","age":20,"gender":"男"},
{"name":"沙和尚","age":21,"gender":"男"}
]
123456
index.html
var Ajax = {
get: function (url, fn) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200 || xhr.status == 304) {
fn.call(this, xhr.responseText);
}
};
xhr.send();
},
post: function (url, data, fn) {
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
fn.call(this, xhr.responseText);
}
};
xhr.send(data);
}
};
// 演示GET请求
Ajax.get("users.json", function (response) {
console.log(response);
});
// 演示POST请求
Ajax.post("users.json", "", function (response) {
console.log(response);
});
控制台:
Cookie
Cookie概述
Cookie 是一些数据,存储于你电脑上的文本文件中,当 web 服务器向浏览器发送 web 页面时,在连接关闭后,服务端不会记录用户的信息,Cookie 的作用就是用于解决 “如何记录客户端的用户信息”:
- 当用户访问 web 页面时,它的名字可以记录在 cookie 中。
- 在用户下一次访问该页面时,可以在 cookie 中读取用户访问记录。
Cookie 以名/值对形式存储,如下所示:
username=zhangsan
当浏览器从服务器上请求 web 页面时, 属于该页面的 cookie 会被添加到该请求中,服务端通过这种方式来获取用户的信息。
JavaScript 可以使用 document.cookie 属性来创建 、读取、及删除 Cookie。
Cookie创建
JavaScript 中,创建 cookie 如下所示:
document.cookie = "username=zhangsan";
您还可以为 cookie 添加一个过期时间(以 UTC 或 GMT 时间)。默认情况下,cookie 在浏览器关闭时删除。
document.cookie = "username=zhangsan; expires=Thu, 18 Dec 2043 12:00:00 GMT";
您可以使用 path 参数告诉浏览器 cookie 的路径。默认情况下,cookie 属于当前页面。
document.cookie = "username=zhangsan; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";
Cookie读取
JavaScript 中,读取 cookie 如下所示:
document.cookie 将以字符串的方式返回所有的 cookie,类型格式: cookie1=value; cookie2=value; cookie3=value;
document.cookie = "username=zhangsan";
var cookies = document.cookie;
console.log(cookies);
Cookie修改
JavaScript 中,修改 cookie 如下所示:
使用 document.cookie 将旧的 cookie 将被覆盖就是修改。
document.cookie = "username=zhangsan";
document.cookie = "username=lisi";
var cookies = document.cookie;
console.log(cookies);
Cookie删除
JavaScript 中,删除 cookie 如下所示:
删除 cookie 非常简单,您只需要设置 expires 参数为以前的时间即可,如下所示,设置为 Thu, 01 Jan 1970 00:00:00 GMT:
document.cookie = "username=zhangsan";
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
var cookies = document.cookie;
console.log(cookies);
Cookie值设置函数
/**
* Cookie值设置函数
* @param cname cookie名称
* @param cvalue cookie值
* @param exdays 过期天数
*/
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires;
}
Cookie值获取函数
/**
* Cookie值获取函数
* @param cname cookie名称
* @returns {string}
*/
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
}
return "";
}
WebStorage
WebStorage概述
WebStorage是HTML5中本地存储的解决方案之一,在HTML5的WebStorage概念引入之前除去IE User Data、Flash Cookie、Google Gears等看名字就不靠谱的解决方案,浏览器兼容的本地存储方案只有使用Cookie。有同学可能会问,既然有了Cookie本地存储,为什么还要引入WebStorage的概念?那就要说一说Cookie的缺陷了:
- 数据大小:作为存储容器,Cookie的大小限制在4KB左右这是非常坑爹的,尤其对于现在复杂的业务逻辑需求,4KB的容量除了存储一些配置字段还简单单值信息,对于绝大部分开发者来说真的不知指望什么了。
- 安全性问题:由于在HTTP请求中的Cookie是明文传递的(HTTPS不是),带来的安全性问题还是很大的。
- 网络负担:我们知道Cookie会被附加在每个HTTP请求中,在HttpRequest和HttpResponse的header中都是要被传输的,所以无形中增加了一些不必要的流量损失。
虽然WebStorage是HTML5新增的本地存储解决方案之一,但并不是为了取代Cookie而制定的标准,Cookie作为HTTP协议的一部分用来处理客户端和服务器通信是不可或缺的,session正是依赖于实现的客户端状态保持。WebStorage的意图在于解决本来不应该Cookie做,却不得不用Cookie的本地存储的应用场景。
WebStorage分类
Web Storage又分为两种: sessionStorage 和localStorage ,即这两个是Storage的一个实例。从字面意思就可以很清楚的看出来,sessionStorage将数据保存在session中,浏览器关闭也就没了;而localStorage则一直将数据保存在客户端本地; 不管是sessionStorage,还是localStorage,使用的API都相同。
localStorage和sessionStorage只能存储字符串类型,对于复杂的对象可以使用ECMAScript提供的JSON对象的stringify和parse来处理,低版本IE可以使用json2.js
localStorage方法
对象介绍:
localStorage在本地永久性存储数据,除非显式将其删除或清空。
常见方法:
- 保存单个数据:localStorage.setItem(key,value);
- 读取单个数据:localStorage.getItem(key);
- 删除单个数据:localStorage.removeItem(key);
- 删除所有数据:localStorage.clear();
- 获取某个索引的key:localStorage.key(index);
案例演示:
// 保存数据
localStorage.setItem("username", "zhangsan");
// 读取单个数据
console.log(localStorage.getItem("username"));
console.log("===============");
// 删除单个数据
localStorage.removeItem("username");
console.log(localStorage.getItem("username"));
console.log("===============");
// 保存两个数据
localStorage.setItem("age", 18);
localStorage.setItem("sex", "男");
console.log("age=" + localStorage.getItem("age"));
console.log("sex=" + localStorage.getItem("sex"));
console.log("===============");
// 使用for-in循环来迭代localStorage中的键值对、属性和方法:
for (var key in localStorage) {
console.log(key + "=" + localStorage[key]);
}
console.log("===============");
// 使用for循环来迭代localStorage中的键值对:
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
var value = localStorage.getItem(key);
console.log(key + "=" + value);
}
console.log("===============");
// 删除所有数据
localStorage.clear();
控制台:
sessionStorage方法
对象介绍:
sessionStorage对象存储特定于某个对话的数据,也就是它的生命周期为当前窗口或标签页,一旦窗口或标签页被永久关闭了,那么所有通过sessionStorage存储的数据也就被清空了。存储在sessionStorage中的数据可以跨越页面刷新而存在,同时如果浏览器支持,浏览器崩溃并重启之后依然可以使用(注意:Firefox和Weblit都支持,IE则不行)。
因为sessionStorage对象绑定于某个服务器会话,所以当文件在本地运行的时候是不可用的。存储在sessionStorage中的数据只能由最初给对象存储数据的页面访问到,所以对多页面应用有限制。
不同浏览器写入数据方法略有不同。Firefox和Webkit实现了同步写入,所以添加到存储空间中的数据是立刻被提交的。而IE的实现则是异步写入数据,所以在设置数据和将数据实际写入磁盘之间可能有一些延迟。
常见方法:
- 保存单个数据:sessionStorage.setItem(key,value);
- 读取单个数据:sessionStorage.getItem(key);
- 删除单个数据:sessionStorage.removeItem(key);
- 删除所有数据:sessionStorage.clear();
- 获取某个索引的key:sessionStorage.key(index);
案例演示:
// 保存数据
sessionStorage.setItem("username", "zhangsan");
// 读取单个数据
console.log(sessionStorage.getItem("username"));
console.log("===============");
// 删除单个数据
sessionStorage.removeItem("username");
console.log(sessionStorage.getItem("username"));
console.log("===============");
// 保存两个数据
sessionStorage.setItem("age", 18);
sessionStorage.setItem("sex", "男");
console.log("age=" + sessionStorage.getItem("age"));
console.log("sex=" + sessionStorage.getItem("sex"));
console.log("===============");
// 使用for-in循环来迭代sessionStorage中的键值对、属性和方法:
for (var key in sessionStorage) {
console.log(key + "=" + sessionStorage[key]);
}
console.log("===============");
// 使用for循环来迭代sessionStorage中的键值对:
for (var i = 0; i < sessionStorage.length; i++) {
var key = sessionStorage.key(i);
var value = sessionStorage.getItem(key);
console.log(key + "=" + value);
}
console.log("===============");
// 删除所有数据
sessionStorage.clear();
控制台:
Closure
闭包引入
需求信息:点击某个按钮,提示”点击的是第n个按钮”
第一种解决方法:将btn所对应的下标保存在btn上
var btns = document.getElementsByTagName('button');
//将btn所对应的下标保存在btn上
for (var i = 0, length = btns.length; i < length; i++) {
var btn = btns[i];
btn.index = i;
btn.onclick = function () {
alert('第' + (this.index + 1) + '个');
}
}
第二种解决方法:利用闭包延长局部变量的生命周期
var btns = document.getElementsByTagName('button');
// 利用闭包延长局部变量的生命周期
for (var i = 0, length = btns.length; i < length; i++) {
(function (j) {
var btn = btns[j];
btn.onclick = function () {
alert('第' + (j + 1) + '个');
}
})(i);
}
闭包概念
- 如何产生闭包?
- 当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包
- 什么才是闭包?
- 理解一:闭包是嵌套的内部函数(绝大部分人认为)
- 理解二:包含被引用变量(函数)的对象(极少部分人认为)
- 闭包的作用?
- 它的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中
闭包演示
function fun1() {
var a = 2;
function subFun() {
a++;
console.log(a);
}
return subFun;
}
var f1 = fun1();
f1();
f1();
console.log("===============");
function fun2() {
var a = 2;
function subFun() {
a--;
console.log(a);
}
return subFun;
}
var f2 = fun2();
f2();
f2();
console.log("===============");
闭包生命周期
生命周期:
- 产生:在嵌套内部函数定义执行完时就产生了(不是在调用)
- 死亡:在嵌套的内部函数成为垃圾对象时就死亡了
演示说明:
function fn1() {
//此时闭包就已经产生了(函数提升, 内部函数对象已经创建了)
var a = 2;
function fn2() {
a++;
console.log(a);
}
return fn2;
}
var f = fn1();
f(); // 3
f(); // 4
f = null; //闭包死亡(包含闭包的函数对象成为垃圾对象)
闭包应用
闭包应用: 定义JS模块
- 具有特定功能的js文件
- 将所有的数据和功能都封装在一个函数内部(私有的)
- 只向外暴露一个包含n个方法的对象或函数
- 模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能
案例演示:
第一种格式:myModule.js
function myModule() {
//私有数据
var msg = 'Hello, World';
//操作数据的函数
function doSomething() {
console.log('doSomething() ' + msg.toUpperCase());
}
function doOtherthing() {
console.log('doOtherthing() ' + msg.toLowerCase());
}
//向外暴露对象(给外部使用的方法)
return {
doSomething: doSomething,
doOtherthing: doOtherthing
}
}
第一种使用:index.html
var module = myModule();
module.doSomething();
module.doOtherthing();
第二种格式:myModule.js
(function (window) {
//私有数据
var msg = 'Hello, World';
//操作数据的函数
function doSomething() {
console.log('doSomething() ' + msg.toUpperCase());
}
function doOtherthing() {
console.log('doOtherthing() ' + msg.toLowerCase());
}
//向外暴露对象(给外部使用的方法)
window.myModule = {
doSomething: doSomething,
doOtherthing: doOtherthing
}
})(window);
第二种使用:index.html
myModule.doSomething();
myModule.doOtherthing();
ES新特性
ES6
let关键字
let 关键字用来声明变量,使用 let 声明的变量有几个特点:
- 不允许重复声明
- 块儿级作用域
- 不存在变量提升
- 不影响作用域链
注意:以后声明变量使用 let 就对了
const关键字
const 关键字用来声明常量,const 声明有以下特点:
- 不允许重复声明
- 块儿级作用域
- 声明必须赋初始值
- 值不允许修改
- 标识符一般为大写
// 声明常量
const MAX = 100;
console.log(MAX);
// 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错
const TEAM1 = [1, 2, 3, 4];
const TEAM2 = [1, 2, 3, 4];
// 但是不能修改地址指向
// TEAM2 = TEAM1;
注意:声明对象类型使用 const,非对象类型声明选择 let
解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式
- 数组
//数组的解构赋值
const arr = ["张学友", "刘德华", "黎明", "郭富城"];
let [zhang, liu, li, guo] = arr;
console.log(zhang);
console.log(liu);
console.log(li);
console.log(guo);
- 简单对象的
//对象的解构赋值
const lin = {
name: "林志颖",
tags: ["车手", "歌手", "小旋风", "演员"]
};
let {name, tags} = lin;
console.log(name);
console.log(tags);
- 复杂对象的
//复杂对象的解构赋值
let wangfei = {
name: "王菲",
age: 18,
songs: ["红豆", "流年", "暧昧"],
history: [
{name: "窦唯"},
{name: "李亚鹏"},
{name: "谢霆锋"}
]
};
let {name, age, songs: [one, two, three], history: [first, second, third]} = wangfei;
console.log(name);
console.log(age);
console.log(one);
console.log(two);
console.log(three);
console.log(first);
console.log(second);
console.log(third);
模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:
- 字符串中可以出现换行符
//定义字符串
let str = `<ul>
<li>沈腾</li>
<li>玛丽</li>
<li>魏翔</li>
<li>艾伦</li>
</ul>`;
console.log(str);
- 可以使用 ${xxx} 形式输出变量
//变量拼接
let name = '小可爱';
let result = `欢迎${name}访问我的文章`;
console.log(result);
注意:当遇到字符串与变量拼接的情况使用模板字符串
对象简化写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法,这样的书写更加简洁。
注意:对象简写形式简化了代码,所以以后用简写就对了
let name = "张三";
let age = 18;
let speak = function () {
console.log(this.name);
};
//属性和方法简写
let person = {
name,
age,
speak
};
console.log(person.name);
console.log(person.age);
person.speak();
箭头函数
ES6 允许使用「箭头」(=>)定义函数,通用写法如下:
let fn = (arg1, arg2, arg3) => {
return arg1 + arg2 + arg3;
}
箭头函数的注意点:
- 如果形参只有一个,则小括号可以省略
- 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
- 箭头函数 this 指向声明时所在作用域下 this 的值,箭头函数不会更改 this 指向,用来指定回调函数会非常合适
- 箭头函数不能作为构造函数实例化
- 不能使用 arguments 实参
this指向问题
// this 指向声明时所在作用域中 this 的值
let fn = () => {
console.log(this);
}
fn();
let school = {
name: "张三",
getName() {
let subFun = () => {
console.log(this);
}
subFun();
}
};
school.getName();
rest参数
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments 参数。
注意:rest 参数非常适合不定个数参数函数的场景
// 作用与 arguments 类似
function add(...args) {
console.log(args);
}
add(1, 2, 3, 4, 5);
// rest 参数必须是最后一个形参
function minus(a, b, ...args) {
console.log(a, b, args);
}
minus(100, 1, 2, 3, 4, 5, 19);
spread扩展运算符
扩展运算符(spread)也是三个点(…),它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。
// 展开数组
let tfboys = ["德玛西亚之力", "德玛西亚之翼", "德玛西亚皇子"];
function fn() {
console.log(arguments);
}
fn(...tfboys);
// 展开对象
let skillOne = {
q: "致命打击"
};
let skillTwo = {
w: "勇气"
};
let skillThree = {
e: "审判"
};
let skillFour = {
r: "德玛西亚正义"
};
let gailun = {...skillOne, ...skillTwo, ...skillThree, ...skillFour};
console.log(gailun);
Symbol类型
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值,它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型,Symbol 特点如下:
- Symbol 的值是唯一的,用来解决命名冲突的问题
- Symbol 值不能与其它数据进行运算
- Symbol 定义的对象属性不能使用 for…in 循环遍 历 ,但是可以使用 Reflect.ownKeys 来获取对象的所有键名
注意:遇到唯一性的场景时要想到 Symbol
创建 Symbol
let s1 = Symbol();
console.log(s1);
console.log(typeof s1);
//添加标识的 Symbol
let s2 = Symbol("张三");
let s2_2 = Symbol("张三");
console.log(s2);
console.log(s2_2);
console.log(s2 === s2_2);
//使用 Symbol for 定义
let s3 = Symbol.for("张三");
let s3_2 = Symbol.for("张三");
console.log(s3);
console.log(s3_2);
console.log(s3 === s3_2);
//在方法中使用 Symbol
let game = {
name: "狼人杀",
[Symbol('say')]: function () {
console.log("我可以发言")
},
[Symbol('zibao')]: function () {
console.log('我可以自爆');
}
};
console.log(game);
Symbol内置值
除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。
可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。
内置值 | 描述 |
---|---|
Symbol.hasInstance | 当其它对象使用 instanceof 运算符,判断是否为该对象的实例时,会调用这个方法 |
Symbol.isConcatSpreadable | 对象的 Symbol.isConcatSpreadable 属性等于的是一个布尔值,表示该对象用于 Array.prototype.concat()时, 是否可以展开 |
Symbol.species | 创建衍生对象时,会使用该属性 |
Symbol.match | 当执行 str.match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值 |
Symbol.replace | 当该对象被 str.replace(myObject)方法调用时,会返回该方法的返回值 |
Symbol.search | 当该对象被 str.search (myObject)方法调用时,会返回该方法的返回值 |
Symbol.split | 当该对象被 str.split(myObject)方法调用时,会返回该方法的返回值 |
Symbol.iterator | 当对象进行 for…of 循环时,会调用 Symbol.iterator 方法, 返回该对象的默认遍历器 |
Symbol.toPrimitive | 当对象被转为原始类型的值时,会调用这个方法,返 回该对象对应的原始类型值 |
Symbol. toStringTag | 当对象上面调用 toString 方法时,返回该方法的返 回值 |
Symbol. unscopables | 当对象指定了使用 with 关键字时,哪些属性会被 with 环境排除 |
迭代器
遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。ES6 创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 消费,原生具备 iterator 接口的数据:
- Array
- Arguments
- Set
- Map
- String
- TypedArray
- NodeList
注意:需要自定义遍历数据的时候,要想到迭代器
工作原理
1. 创建一个指针对象,指向当前数据结构的起始位置
2. 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
3. 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
4. 每调用 next 方法返回一个包含 value 和 done 属性的对象
遍历数组
//声明一个数组
const xiyou = ["唐僧", "孙悟空", "猪八戒", "沙僧"];
//使用 for...of 遍历数组
for (let v of xiyou) {
console.log(v);
}
console.log("===============");
//获取迭代器对象
let iterator = xiyou[Symbol.iterator]();
//调用对象的next方法
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
自定义遍历数据**
//声明一个对象
const banji = {
name: "五班",
stus: [
"张三",
"李四",
"王五",
"小六"
],
[Symbol.iterator]() {
//索引变量
let index = 0;
let _this = this;
return {
next: function () {
if (index < _this.stus.length) {
const result = {value: _this.stus[index], done: false};
//下标自增
index++;
//返回结果
return result;
} else {
return {value: undefined, done: true};
}
}
};
}
}
//遍历这个对象
for (let v of banji) {
console.log(v);
}
生成器
生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。
生成器函数使用
代码说明:
- 的位置没有限制
- 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到 yield 语句后的值
- yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码
- next 方法可以传递实参,作为 yield 语句的返回值
function * gen() {
/*代码1开始执行*/
console.log("代码1执行了");
yield "一只没有耳朵";
/*代码2开始执行*/
console.log("代码2执行了");
yield "一只没有尾巴";
/*代码3开始执行*/
console.log("代码3执行了");
return "真奇怪";
}
let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log("===============");
//遍历
for (let v of gen()) {
console.log(v);
}
生成器函数参数
function * gen(arg) {
console.log(arg);
let one = yield 111;
console.log(one);
let two = yield 222;
console.log(two);
let three = yield 333;
console.log(three);
}
//执行获取迭代器对象
let iterator = gen('AAA');
console.log(iterator.next());
//next方法可以传入实参
console.log(iterator.next('BBB'));
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));
生成器函数实例
案例演示:1s后控制台输出 111,2s后输出 222,3s后输出 333
function one() {
setTimeout(() => {
console.log(111);
iterator.next();
}, 1000)
}
function two() {
setTimeout(() => {
console.log(222);
iterator.next();
}, 2000)
}
function three() {
setTimeout(() => {
console.log(333);
iterator.next();
}, 3000)
}
function * gen() {
yield one();
yield two();
yield three();
}
//调用生成器函数
let iterator = gen();
iterator.next();
案例演示:模拟获取 ,用户数据 ,订单数据 ,商品数据
function getUsers() {
setTimeout(() => {
let data = "用户数据";
iterator.next(data);
}, 1000);
}
function getOrders() {
setTimeout(() => {
let data = "订单数据";
iterator.next(data);
}, 1000);
}
function getGoods() {
setTimeout(() => {
let data = "商品数据";
iterator.next(data);
}, 1000);
}
function * gen() {
let users = yield getUsers();
console.log(users);
let orders = yield getOrders();
console.log(orders);
let goods = yield getGoods();
console.log(goods);
}
//调用生成器函数
let iterator = gen();
iterator.next();
promise
回调函数
Promise的构造函数,接收一个参数,这个参数是一个回调函数,并传入两个参数:resolve、reject,分别表示异步操执行成功后的回调函数和异步操作执行失败后的回调函数。其实这里用“成功”和“失败”来表述并不准。按照标准来讲,resolve是将Promise的状态设置为fullfiled,reject是将Promise的状态设置为rejected,但是我们暂且可以这么理解。
7.1.12.1、Promise基本使用
//实例化 Promise 对象
const p = new Promise(function (resolve, reject) {
setTimeout(function () {
// 成功调用resolve()处理
let data = "数据读取成功";
resolve(data);
// 失败调用reject()处理
let err = "数据读取失败";
reject(err);
}, 1000);
});
//调用 promise 对象的 then 方法
p.then(function (value) {
console.log(value);
}, function (reason) {
console.error(reason);
});
7.1.12.2、Promise案例演示
案例演示:
// 接口地址: https://api.apiopen.top/getJoke
const p = new Promise((resolve, reject) => {
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化
xhr.open("GET", "https://api.apiopen.top/getJoke");
//3. 发送
xhr.send();
//4. 绑定事件, 处理响应结果
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
//判断响应状态码 200-299
if (xhr.status >= 200 && xhr.status < 300) {
//表示成功
resolve(xhr.response);
} else {
//如果失败
reject(xhr.status);
}
}
}
});
//指定回调
p.then(function (value) {
console.log(value);
}, function (reason) {
console.error(reason);
});
7.1.12.3、Promise-then方法
调用 then 方法,then 方法的返回结果是 Promise 对象,对象状态由回调函数的执行结果决定,如果回调函数中返回的结果是 非 promise 类型的属性,状态为成功,返回值为对象的成功的值
//创建 promise 对象
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("用户数据");
}, 1000)
});
//链式调用+箭头函数
p.then(value => {
console.log(value);
return value;
}).then(value => {
console.log(value);
});
7.1.12.4、Promise-catch方法
如果只想处理错误状态,我们可以使用 catch 方法
const p = new Promise((resolve, reject) => {
setTimeout(() => {
//设置 p 对象的状态为失败, 并设置失败的值
reject("出错啦!");
}, 1000);
});
p.catch(function (reason) {
console.error(reason);
});
Set
ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历,集合的属性和方法:
- size:返回集合的元素个数
- add():增加一个新元素,返回当前集合
- delete():删除元素,返回 boolean 值
- has():检测集合中是否包含某个元素,返回 boolean 值
- clear():清空集合,返回 undefined
//创建一个空集合
let s = new Set();
//创建一个非空集合
let s1 = new Set([1, 2, 3, 1, 2, 3]);
//集合属性与方法
//返回集合的元素个数
console.log(s1.size);
//添加新元素
console.log(s1.add(4));
//删除元素
console.log(s1.delete(1));
//检测是否存在某个值
console.log(s1.has(2));
//清空集合
console.log(s1.clear());
Map
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键” 的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。Map 的属性和方法:
- size:返回 Map 的元素个数
- set():增加一个新元素,返回当前 Map
- get():返回键名对象的键值
- has():检测 Map 中是否包含某个元素,返回 boolean 值
- clear():清空集合,返回 undefined
//创建一个空 map
let m = new Map();
//创建一个非空 map
let m2 = new Map([
["name", "张三"],
["gender", "女"]
]);
//属性和方法
//获取映射元素的个数
console.log(m2.size);
//添加映射值
console.log(m2.set("age", 6));
//获取映射值
console.log(m2.get("age"));
//检测是否有该映射
console.log(m2.has("age"));
//清除
console.log(m2.clear());
Class类
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class 关键字,可以定义类。基本上,ES6 的 class 可以看作只是 一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已,它的一些如下:
- class:声明类
- constructor:定义构造函数初始化
- extends:继承父类
- super:调用父级构造方法
- static:定义静态方法和属性
//父类
class Phone {
//构造方法
constructor(brand, color, price) {
this.brand = brand;
this.color = color;
this.price = price;
}
//对象方法
call() {
console.log("我可以打电话!!!")
}
}
//子类
class SmartPhone extends Phone {
constructor(brand, color, price, screen, pixel) {
super(brand, color, price);
this.screen = screen;
this.pixel = pixel;
}
//子类方法
photo() {
console.log("我可以拍照!!");
}
playGame() {
console.log("我可以玩游戏!!");
}
//方法重写
call() {
console.log("我可以进行视频通话!!");
}
//静态方法
static run() {
console.log("我可以运行程序")
}
static connect() {
console.log("我可以建立连接")
}
}
//实例化对象
const Nokia = new Phone("诺基亚", "灰色", 230);
const iPhone6s = new SmartPhone("苹果", "白色", 6088, "4.7inch", "500w");
//调用子类方法
iPhone6s.playGame();
//调用重写方法
iPhone6s.call();
//调用静态方法
SmartPhone.run();
数值拓展
对象扩展
ES6 新增了一些 Object 对象的方法,例如:
- Object.is:比较两个值是否严格相等,与『===』行为基本一致(+0 与 NaN)
- Object.assign:对象的合并,将源对象的所有可枚举属性,复制到目标对象
- proto、setPrototypeOf、 setPrototypeOf可以直接设置对象的原型
7.1.17.1、Object.is
Object.is:判断两个值是否完全相等
console.log(Object.is(120, 120));// ===
console.log(Object.is(NaN, NaN));// ===
console.log(NaN === NaN);// ===
7.1.17.2、Object.assign
Object.assign:对象的合并,后边的对象会把前边对象的相同属性和方法覆盖,没有的属性和方法会合并
const config1 = {
host: "localhost",
port: 3306,
name: "zhangsan",
pass: "root",
test1: "test1"
};
const config2 = {
host: "127.0.0.1",
port: 3309,
name: "lisi",
pass: "root",
test2: "test2"
}
console.log(Object.assign(config1, config2));
7.1.17.3、设置原型对象
- Object.setPrototypeOf:设置原型对象
- Object.getPrototypeof:获取原型对象
const school = {
name: "MySchool"
};
const cities = {
xiaoqu: ["北京", "上海", "深圳"]
};
Object.setPrototypeOf(school, cities);
console.log(Object.getPrototypeOf(school));
console.log(school);
模块化
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块化的好处
- 防止命名冲突
- 代码复用
- 高维护性
模块化的产品
CommonJS => NodeJS、Browserify
AMD => requireJS
CMD => seaJS
模块化的语法
模块功能主要由两个命令构成:export 和 import。
- export 命令用于规定模块的对外接口
- import 命令用于输入其它模块提供的功能
模块化的暴露
m1.js
//方式一:分别暴露
export let school = "华北理工大学";
export function study() {
console.log("我们要学习!");
}
m2.js
//方式二:统一暴露
let school = "华北理工大学";
function findJob() {
console.log("我们要找工作!");
}
export {school, findJob};
m3.js
//方式三:默认暴露
export default {
school: "华北理工大学",
change: function () {
console.log("我们要改变自己!");
}
}
模块化的导入
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
<script type="module">
// 引入 m1.js 模块内容
import * as m1 from "./m1.js";
// 引入 m2.js 模块内容
import * as m2 from "./m2.js";
// 引入 m3.js 模块内容
import * as m3 from "./m3.js";
m1.study();
m2.findJob();
m3.default.change();
</script>
</body>
</html>
解构赋值形式
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
<script type="module">
// 引入 m1.js 模块内容
import {school, study} from "./m1.js";
// 引入 m2.js 模块内容
import {school as s, findJob} from "./m2.js";
// 引入 m3.js 模块内容
import {default as m3} from "./m3.js";
console.log(school);
study();
console.log(s);
findJob();
console.log(m3);
m3.change();
</script>
</body>
</html>
注意:针对默认暴露还可以直接
import m3 from "./m3.js"
浅拷贝、深拷贝
如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝;如果B没变,那就是深拷贝,深拷贝与浅拷贝的概念只存在于引用数据类型。
ES7
数组方法拓展
Array.prototype.includes:此方法用来检测数组中是否包含某个元素,返回布尔类型值
const mingzhu = ["西游记", "红楼梦", "三国演义", "水浒传"];
console.log(mingzhu.includes("西游记"));
幂运算
**
操作符的作用和 Math.pow
的作用是一样,请看代码:
console.log(2 ** 10);
console.log(Math.pow(2, 10));
ES8
async 函数的语法:
async function fn(){
}
async 函数的返回值:
- 返回的结果不是一个 Promise 类型的对象,返回的结果就是成功 Promise 对象
- 返回的结果如果是一个 Promise 对象,具体需要看执行resolve方法还是reject方法
- 抛出错误,返回的结果是一个失败的 Promise
async 函数的演示:
//async 函数
async function fn() {
return new Promise((resolve, reject) => {
resolve('成功的数据');
// reject("失败的错误");
});
}
const result = fn();
//调用 then 方法
result.then(value => {
console.log(value);
}, reason => {
console.warn(reason);
});
7.3.2、await 表达式
async 和 await 两种语法结合可以让异步代码像同步代码一样
await 表达式的注意事项:
- await 必须写在 async 函数中
- await 右侧的表达式一般为 promise 对象
- await 返回的是 promise 成功的值
- await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理
await 表达式的语法演示:
//创建 promise 对象
const p = new Promise((resolve, reject) => {
resolve("用户数据");
//reject("失败啦!");
})
//await 要放在 async 函数中.
async function fun() {
try {
let result = await p;
console.log(result);
} catch (e) {
console.log(e);
}
}
//调用函数
fun();
await 表达式的案例演示:async与await封装AJAX请求
// 发送 AJAX 请求, 返回的结果是 Promise 对象
function sendAJAX(url) {
return new Promise((resolve, reject) => {
//1. 创建对象
const x = new XMLHttpRequest();
//2. 初始化
x.open('GET', url);
//3. 发送
x.send();
//4. 事件绑定
x.onreadystatechange = function () {
if (x.readyState === 4) {
if (x.status >= 200 && x.status < 300) {
resolve(x.response);//成功
} else {
reject(x.status);//失败
}
}
}
})
}
// async 与 await 测试
async function fun() {
//发送 AJAX 请求 1
let joke = await sendAJAX("https://api.apiopen.top/getJoke");
//发送 AJAX 请求 2
let tianqi = await sendAJAX('https://www.tianqiapi.com/api/?version=v1&city=%E5%8C%97%E4%BA%AC&appid=23941491&appsecret=TXoD5e8P')
console.log(joke);
console.error(tianqi);//为了区别数据,我这里用红色的error输出
}
// 调用函数
fun();
对象方法拓展
- Object.keys()方法返回一个给定对象的所有可枚举键值的数组
- Object.values()方法返回一个给定对象的所有可枚举属性值的数组
- Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组
//声明对象
const person = {
name: "张三",
age: 20
};
//获取对象所有的键
console.log(Object.keys(person));
//获取对象所有的值
console.log(Object.values(person));
//获取对象所有的键值对数组
console.log(Object.entries(person));
//创建 Map
const m = new Map(Object.entries(person));
console.log(m.get("name"));
Object.getOwnPropertyDescriptors方法返回指定对象所有自身属性的描述对象
//声明对象
const person = {
name: "张三",
age: 20
};
//对象属性的描述对象
console.log(Object.getOwnPropertyDescriptors(person));
//声明对象
const obj = Object.create(null, {
name: {
//设置值
value: "李四",
//属性特性
writable: true,
configurable: true,
enumerable: true
},
age: {
//设置值
value: 21,
//属性特性
writable: true,
configurable: true,
enumerable: true
}
});
//对象属性的描述对象
console.log(Object.getOwnPropertyDescriptors(obj));
ECMAScript9新特性
对象拓展
Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符
对象展开
function connect({host, port, ...user}) {
console.log(host);
console.log(port);
console.log(user);
}
connect({
host: '127.0.0.1',
port: 3306,
username: 'root',
password: 'root',
type: 'master'
});
对象合并
const skillOne = {
q: '天音波'
};
const skillTwo = {
w: '金钟罩'
};
const skillThree = {
e: '天雷破'
};
const skillFour = {
r: '猛龙摆尾'
};
const mangseng = {...skillOne, ...skillTwo, ...skillThree, ...skillFour};
console.log(mangseng);