JavaScript
- 引入方法
- 输入输出
- 变量
-
- var命令
- 数据类型
-
- number
- string
- boolean
- null
- undefined
- array
- object
- symbol(ES6增加的基本数据类型)
- 判断类型——类型运算符
- 变量提升
- 比较语句
- 循环语句
- 运算符
- 类
-
- 原型 prototype
- 原型链 __ proto__
- 继承
-
- js继承机制:基于原型的继承机制
- this 指向
- 函数
-
- 作用域
- 函数提升
- 常见两种错误类型
- 闭包
-
- 应用:点击事件中输出循环中对应的 i
- 函数节流 throttle
- 函数防抖 debounce
- 事件
-
- 鼠标相关事件
- 键盘相关事件
- 事件监听
-
- 直接把事件的方法写在页面结构上
- 事件绑定:给事件属性赋值.onclick
- addEventListener / removeEventListener
- attachEvent / detachEvent
- 阻止浏览器默认行为
-
- 让a标签失效,不跳转不刷新页面
- 事件流
- 事件冒泡、捕获
-
- 阻止事件冒泡
- 冒泡事件流
- 捕获事件流
- 事件委托
-
- 后生成元素的事件绑定问题
- 事件循环
- 任务队列
-
- 宏任务
- 微任务
- 浏览器对象模型 BOM
-
- window对象
-
- 窗口尺寸
- 其他方法
-
- 新建窗体
- 窗体控制(不常用)
- 窗体滚动轴控制
- 窗体焦点控制
- window.history 对象
- window.location 对象
- window.navigator 对象
- window.screen 对象
- document 对象
-
- cookie
-
- document.cookie 属性
- window.frames 对象
- 三种类型的弹出框
-
- window.alert() 警告框
- window.confirm() 确认框
- window.prompt() 提示框
- 折行
- 定时事件( Timing Events)
-
- window.setTimeout()
- window.setInterval()
- 文档对象模型 DOM
-
- DOM编程界面
- 获取元素的常用方法
- 节点
-
- 类型
- 节点属性
- 节点的操作(方法)
- 获取设置样式
- 动画
- jQuery
-
- jq底层原理
- 文档就绪函数
- 获取jQuery 对象
- 与原生对象转化
- jQuery 选择器
- 属性 / CSS
- 事件
-
- 事件绑定
-
- 后生成元素事件绑定
- 自动获取焦点
- 鼠标事件
- jQuery简单仿写
- AJAX
-
- AJAX的优点:
- AJAX原理/原生AJAX
-
- 创建 XMLHttpRequest 对象,有兼容性问题
- 向服务器发送请求
-
- get 和 post 区别:
- 服务器响应
- readyState — >XMLHttpRequest 的状态
- status 状态码:
-
- 完整的HTTP状态码如下:
- 优点
- 缺点
- 在浏览器地址栏里输入一个地址回车
- ES6
-
- 作用域
- 声明
-
- const 命令
- let 命令
- let 与 var 的区别
- 变量的解构赋值
- 对象扩展
-
- 对象的属性和方法的简写方式
- 新增的方法
-
- Object.is()
- symbol 增加的基本数据类型
- 箭头函数 =>
-
- this 指向
- 箭头函数不能用于构造函数
- 箭头函数中不能使用arguments(类数组)
- 运算符
-
- rest 运算符
- ... 扩展运算符
- set()
- map()
- Promise
-
- 使用的2个步骤
- Promise 对象的三个状态
- generator
-
- 特点
- ES7 :async函数 await 异步回调
-
- 语法
- 特点
- defer和async
引入方法
1、body内嵌套:html结构加载完就会执行script
<body>
<script>
</script>
</body>
2、head 内文件引用:
<script src=""></script>
3、head内直接嵌套:可能取不到下面元素
<head>
<script>
</script>
</head>
解决方法:
window.onload
等页面中资源加载完才会执行
写多个window.onload时,后面的会覆盖前面的
<head>
<script>
window.onload = function(){
......
}
</script>
</head>
输入输出
输入
弹框提示输入:
var 变量名 = prompt();
输出
1、控制台输出:
console.log();
2、页面输出:
document.write();
3、弹框输出:
alert();
变量
var命令
JavaScript中的变量用var声明,是弱类型。变量名区分大小写,允许包含字母、数字、美元符号($)和下划线,但第一个字符不允许是数字,不允许包含空格和其他标点符号
数据类型
基本数据类型: number(数值型)、string(字符串)、boolean(布尔值)、null(空)、undefined(未定义)
引用数据类型: array(数组)、object(对象)
number
NaN属性 是代表非数字值的特殊值,该属性用于指示某个值不是数字。
Number.NaN是一个特殊值,说明某些算术运算(如求负数的平方根)的结果不是数字。
用 isNaN() 全局函数——判断一个值是否是 NaN 值。
string
1、string.length 返回字符串的长度
2、parseInt:字符串转整型
var str = "124.2345";
console.log( parseInt(str) );
//输出结果:124
3、parseFloat:字符串转浮点型
var str = "124.2345";
console.log( parseFloat(str) );
//输出结果:124.234
4、charAt():返回在指定位置的字符。
5、concat():连接两个或多个字符串。
6、indexOf():返回某个指定的字符串值在字符串中首次出现的位置,找不到返回-1
7、lastIndexOf():返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索。
8、replace() :用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
9、slice():提取字符串的片断,并以新的字符串中返回被提取的部分。
10、split():把一个字符串分割成字符串数组。
11、substr(start,length):在字符串中抽取从 start 下标开始的指定数目的字符。
boolean
取值情况:
1、字符串:非空即为真
2、数值:非0即为真
3、undefined null:假
快速输出一个字符串变量的布尔值:
null
表示一个“空”的值。
使用情况:
1、取不到id为div2元素的返回null
2、object 表示为空对象
undefined
表示“未定义”
使用情况:
1、定义变量没有赋值
var a;
console.log(a);
console.log( typeof a);//undefined
2、函数没有返回值 默认返回undefined
function b(){
}
console.log( b() );
3、访问数组越界
4、访问对象没有的属性
5、判断函数参数是否传递
array
1、concat:连接两个或更多的数组,并返回结果。返回新的数组。
2、join:把数组的所有元素放入一个字符串,元素通过指定的分隔符进行分隔。 返回字符串。
解决字符串拼接:先将字符串转化为数组,然后调用join实现字符串拼接
arr.push(str);
return arr.join("");
3、pop:用于删除并返回数组的最后一个元素。 修改原数组。
4、shift:删除并返回数组的第一个元素。
5、push:方法可向数组的末尾添加一个或多个元素并返回新的长度。 修改原数组。
6、reverse:用于颠倒数组中元素的顺序,该方法会改变原来的数组。返回原数组。
7、slice:可从已有的数组中返回选定的元素。 返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。
8、sort:用于对数组的元素进行排序。 数组在原数组上进行排序。
//从小到大排序
var a9 = [];
a8.sort(function(a,b){
return a-b;
})
//从大到小排序
var a10 = a8.sort(function(a,b){
return b-a;
})
9、splice:
splice(index,howmany,item,…) 向/从数组中添加/删除项目,然后返回被删除的项目。
该方法会改变原始数组。
index:必需;整数;规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
howmany:必需;要删除的项目数量,如果设置为 0,则不会删除项目。
item:可选;向数组添加的新项目。
object
1、取对象的属性
可变的、动态的 属性———> [ ]
var person1 = {
name : "zs";
age :10;
}
var person2 = {};
for(key in person1) //循环对象属性
{
console.log(key); //输出属性名
console.log(person1[key]); //输出属性值
person2[key] = person1[key];
}
写死的属性 —> .
2、克隆对象,返回一个新对象
var person1 = {
name : "zs",
age :10,
father:{
name:"zxx",
age:40
}
}
function clone (obj){
var result = {};
for(var key in obj){
result[key] = obj[key];
}
return result;
}
var person3 = clone (person1);
person1.name = "lisi";
person1.father.name = "zyy";
console.log(person3);
//person3.name = "zs"
//person3.father.name = "zyy"
如果克隆的属性是对象——>深克隆
//递归调用clone函数进行深克隆
if(typeof obj[key] == "object"){
result[key] = clone (obj[key]);
}else{
result[key] = obj[key];
}
symbol(ES6增加的基本数据类型)
let name = Symbol();
obj[name] = ‘XX';
// 该属性不会出现在for...in、for...of循环中
判断类型——类型运算符
判断数据类型:typeof **
1、typeof “123” —— “string”
2、typeof 123 —— “number”
3、typeof true —— “boolean”
4、typeof undefined —— “undefined”
5、typeof {name:‘zs’} —— “object”
6、typeof null —— “object”
7、typeof [1, 2, 3] —— “object”
8、typeof 函数名 —— “function”
在使用 typeof 运算符时采用引用类型**存储值会出现一个问题,无论引用的是什么类型的对象,它都返回 “object”。
判断数组和对象
1、Array.isArray() —— 数组(true); 对象(false)
2、instanceof:
具体实例化对象 instanceof Array —— 数组(true); 对象(false)
具体实例化对象 instanceof Object —— 数组(false);对象(true)
3、具体实例化对象object.constructor 返回构造函数
变量提升
var 定义的变量会发生变量提升 :当前作用域的最上边声明变量但是没有赋值
console.log(a);
var a = 5; //报错 : undefined
//相当于:
var a;
console.log(a);
a=5;
var a = 5;
function fn(){
( var a; )
console.log(a);
var a = 10;
} //输出:undefined 变量提升
var a = 5;
function fn(){
console.log(a);
a = 10;
} //输出:5
var a = 5;
function fn(){
var a = 10;
console.log(a);
} //输出:10
比较语句
if-else
使用 if 来规定要执行的代码块,如果指定条件为 true
使用 else 来规定要执行的代码块,如果相同的条件为 false
使用 else if 来规定要测试的新条件,如果第一个条件为 false
var condition = false;
if (condition) {
alert("我不会出现!");
}
else {
alert("我会出现!");
}
switch-case
使用 switch 来规定多个被执行的备选代码块
var a = '3';
switch(a) {
case 4:
alert("4");
break;
case '3':
alert("3");
break;
case 2:
alert("2");
break;
case 1:
alert("1");
break;
default:
alert('错误。。。');
}
//执行结果:弹框显示3
循环语句
for:多次遍历代码块
for/in:遍历对象属性
while:当指定条件为 true 时循环一段代码块
do/while:当指定条件为 true 时循环一段代码块
while
while( num > 0 ){
console.log(num);
num--;
}
do-while
do{
console.log(num);
num--;
}while( num > 0);
运算符
赋值运算符
作用:把值赋给变量
赋值运算符 | 示例 | 等同表达 |
---|---|---|
= | x = y | x = y |
+= | x += y | x = x + y |
-= | x -= y | x = x - y |
*= | x * y | x = x * y |
/= | x /= y | x = x / y |
%= | x %= y | x = x % y |
算数运算符
+、++
1、+
应用:字符串拼接 、 数学运算
x = 7 + 8; //15
y = "7" + 8; //78
z = "Hello" + 7; //Hello7
2、++ (递加)
c++;
先参与运算 再++
++c;
先++ 再参与运算
-、–(递减)、*、/、%
能转成数值型——做运算 ;转不了输出NaN
比较运算符
比较运算符 | 描述 |
---|---|
== | 等于 |
=== | 等值等型 |
!= | 不相等 |
!== | 不等值或不等型 |
> | 大于 |
< | 小于 |
>= | 大于或等于 |
<= | 小于或等于 |
? : | 三目运算符 |
逻辑运算符
逻辑运算符 | 描述 |
---|---|
&& | 逻辑与 |
|| | 逻辑或 |
! | 逻辑非 |
类型运算符
类型运算符 | 描述 |
---|---|
typeof | 返回变量的类型 |
instanceof | 如果对象是对象类型的实例返回 true |
位运算符
位运算符处理 32 位数,该运算中的任何数值运算数都会被转换为 32 位的数,结果会被转换回 JavaScript 数
运算符 | 描述 | 例子 | 等同于 | 结果 | 十进制 |
---|---|---|---|---|---|
& | 与 | 5 & 1 | 0101 & 0001 | 0001 | 1 |
|| | 或 | 5 || 1 | 0101 || 0001 | 0101 | 5 |
~ | 非 | ~ 5 | ~0101 | 1010 | 10 |
^ | 异或 | 5 ^ 1 | 0101 ^ 0001 | 0100 | 4 |
<< | 零填充左位移 | 5 << 1 | 0101 << 1 | 1010 | 10 |
>> | 有符号右位移 | 5 >> 1 | 0101 >> 1 | 0010 | 2 |
>>> | 零填充右位移 | 5 >>> 1 | 0101 >>> 1 | 0010 | 2 |
上例使用 4 位无符号的例子。但是 JavaScript 使用 32 位有符号数。
因此,在 JavaScript 中,~ 5 不会返回 10,而是返回 -6。
~00000000000000000000000000000101 将返回 11111111111111111111111111111010
类
类:具有相同属性和方法的集合。
原型 prototype
构造函数有一个prototype属性,这个属性是一个指针,指向它的原型对象
原型对象下的属性和方法 可以被实例化对象所共享
原型下有一个constructor 属性指向它的构造函数
原型链 __ proto__
当从一个对象那里调取属性或方法时,如果该对象自身不存在这样的属性或方法,就会去自己关联的prototype对象那里寻找,
如果prototype没有,就会去prototype关联的前辈prototype那里寻找,
如果再没有,则继续查找Prototype.Prototype引用的对象,以此类推,
直到Prototype. … .Prototype为undefined(Object的Prototype就是undefined),从而形成了原型链
继承
调用父类.call(this, ) 继承属性:
function Coder(name, age) {
Person.call(this, name, age);
}
继承父类的方法:
Coder.Prototype = new Person();
//需要手动把 Coder 的原型对象下的 constructor属性 指向Coder
Coder.prototype.constructor = Coder;
js继承机制:基于原型的继承机制
举个例子来说:假设有一个ClassA和ClassB,ClassB想继承ClassA
首先要在ClassA的构造函数里定义属性,在ClassA的原型里定义方法:
function ClassA() {
this.color = sColor;
}
ClassA.prototype.sayColor = function () {
alert(this.color);
};
然后在ClassB的构造函数中使用ClassA.call(this)来继承ClassA中的属性:
function ClassB() {
ClassA.call(this);
}
再用ClassB.prototype等于ClassA的一个实例对象来继承ClassA中的方法:
this 指向
改变this 指向的方法:call()、apply()、bind()
区别:
1、apply,call 是直接执行函数调用,bind是绑定,执行需要再次调用.
2、apply和call 的区别是apply接受数组作为参数,而call是接受逗号分隔的无限多个参数列表,call bind —> ,,,,;apply —> (this),[,,,,(其它参数)]
3、call(obj,1,2,3,) 从第二个参数开始有多个参数,用来代表函数的实参 apply(obj,[1,2,3]) 第二个参数是一个数组,数组中的每一个元素对应一个实参 bind(obj,1,2,3,)();
// this指向的几种情况:
function a() {
console.log(this);
}
a(); //Window
setTimeout(function(){
console.log(this);
},10); //Window
var aLi = document.getElementsByTagName('li');
for (var i = 0; i < aLi.length; i++) {
aLi[i].onclick = function(){
console.log(this);
}
} //<li>111</li> <li>222</li> <li>333</li>
for (var i = 0; i < aLi.length; i++) {
aLi[i].onclick = function(){
setTimeout(function(){
console.log(this);
},500);
}
} //Window Window Window
for (var i = 0; i < aLi.length; i++) {
aLi[i].onclick = function(){
setTimeout((function(){
console.log(this);
}).bind(this),500);
}
} //<li>111</li> <li>222</li> <li>333</li>
// 构造函数 this指的是new出来的实例化对象
function Person(name,age){
this.name = name,
this.age = age,
this.say = function(){
//console.log( this.name +"Hehe");
console.log(this);
}
}
var p1 = new Person("zs",20);
p1.say();
//Person {age:20, name: "zs", say: f()}
var obj = {
name:'zs',
age:20,
say:function(msg,mag1,msg2){
console.log(this,msg,mag1,msg2);
}
}
obj.say();
//{name: "zs", age:20, say: f} undefined undefined undefined
obj.say("我是obj","哈哈","呵呵");
//{name: "zs", age:20, say: f} "我是obj","哈哈","呵呵"
//改变this指向
var obj2 = {
name:'xiaowu'
}
obj.say.call(obj2,"我是小吴","哈哈","呵呵");
//{name: "xoapwu"} "我是小吴","哈哈","呵呵"
obj.say.apply(obj2,["我是小吴","哈哈","呵呵"]);
//{name: "xoapwu"} "我是小吴","哈哈","呵呵"
obj.say.bind(obj2); //仅改变this指向没有调用
obj.say.bind(obj2,"我是小吴","哈哈","呵呵")();
//{name: "xoapwu"} "我是小吴","哈哈","呵呵"
函数
1、JavaScript 函数是被设计为执行特定任务的代码块,会在某代码调用它时被执行。
2、使用函数的优点:
能够对代码进行复用:只要定义一次代码,就可以多次使用它
能够多次向同一函数传递不同的参数,以产生不同的结果
作用域
全局作用域、函数作用域
优先级:在函数作用域中,局部变量的优先级比同名的全局变量高。
**隐藏全局变量:**如果给一个局部变量或函数的参数声明的名字与某个全局变量的名字相同,那么就会有效地隐藏这个全局变量。
//示例:
var a = 3;
function fn(){
var b= 10; // 局部作用域 局部变量
c = 20; // 不写 var 定义到全局变量
console.log(c +"fn"); //10fn
console.log(a);//3
}
fn();
console.log(c);//20
console.log(b);//undefined
函数提升
console.log( add(2,3) );
function add(x,y){
return x+y;
}
常见两种错误类型
1、is not defined
console.log( add(2,3) );
add = function(x,y){
return x+y;
}
2、is not a function
console.log( add(2,3) );
var add = function(x,y){
return x+y;
}
闭包
含义:外部函数中声明一个内部函数,内部函数引用外部函数中的局部变量,这样当外部函数调用完毕后,外部函数中的变量不释放,可以一直使用。
好处:变量长期驻扎在内存中,避免全局变量的污染(代码模块化),允许私有成员的存在
缺点:可能会造成内存泄露
function a(){
var x = 1;
function b(){
console.log(x);
}
return b;//将内部函数暴露出去
}
var bFn = a();
bFn(); //输出结果:1
应用:点击事件中输出循环中对应的 i
var aLi = document.getElementsByTagName("li");
for(var i=0;i<aLi.length;i++){
//函数的立即调用(声明就调用) —— (function(){......})();
(function(i)
{
aLi[i].onclick = function()
{
console.log(i);
}
}
)(i)
}
函数节流 throttle
一个函数执行一次后,只有大于设定的执行周期才执行第二次
有个需要频繁触发的函数
出于优化性能角度,在规定时间内,只让函数触发第一次生效,后面不生效
用到的知识点:闭包 、this指向
function throttle(fn, delay) {
var startTime = 0;
return function() {
var nowTime = Date.now();
if (nowTime - startTime > delay) {
//fn();
fn.call(this);
startTime = nowTime;
}
}
}
document.onmousemove = throttle(function(){
console.log(Date.now());
console.log(this); // fn()——Window fn.call(this)——document
}, 1000);
函数防抖 debounce
一个需要频繁触发的函数,在规定时间内只让最后一次生效,前面的不生效
function debounce(fn, delay) {
var timer = null;
return function(){
clearTimeout(timer);
timer = setTimeout(function(){
//fn();
fn.apply(this);
}.bind(this), delay);
}
/*
//箭头函数 ES6
return function(){
clearTimeout(timer);
timer = setTimeout(() => {
//fn();
fn.apply(this);
}, delay);
}
*/
}
var oBtn = document.getElementById('btn');
oBtn.onclick = debounce(function(){
console.log(Date.now());
console.log(this);
//fn()——Window {fn.apply(this)}.bind(this)
// 箭头函数——<button id="btn">click</button>
}, 1000);
事件
三要素:事件源 、事件处理函数 、事件
鼠标相关事件
e.clientX:获取鼠标点击时距离可视区(屏幕)左边的距离 (Integer)
e.clientY:获取鼠标点击时距离屏幕上边的距离 (Integer)
键盘相关事件
altKey——Boolean
keyCode——Integer
事件监听
直接把事件的方法写在页面结构上
function eventfun(){
//console.log(this);
}
这里涉及到一个this作用域的问题,eventfun在这里是一个全局函数, 对象是[object Window],this指向的是window。要解决this作用域的问题,可以使用为全局函数添加event变量的方法,在页面结构上将this对象作为参数传递到函数内部使用
function eventfun2(eve){//在这里把事件对象作为参数传递到全局方法里
eve.name="alex";
window.name="robin";
console.log(this);//[object Window]
console.log(eve);// [object HTMLInputElement]
console.log(this.name);// robin
console.log(eve.name);// alexvar
self=eve;
console.log(this.name);//robin
console.log(self.name);//alex
alert(window.name);
alert(self.name);
}
事件绑定:给事件属性赋值.onclick
局限性:只能为事件绑定一个方法,如果绑定多个就会以后一个方法为准
使用这种为事件属性赋值的方法,this的指针会指向window对象,而不是被事件对象,所以这种方法是引用
HTMLElementobject.onclick = fucntion(){
fun1();
fun2();
fun3();
console.log(this);//window.object
}
function dosomething(){
//js code
}
HTMLElementobject.onclick = dosomething;
//使用这种为事件对象属性赋值的形式,this指针指向事件执行对象
console.log(this);//htmlElementObject
addEventListener / removeEventListener
obj.addEventListener(evtype,fn,useCapture):
W3C提供的添加事件处理函数的方法。
obj是要添加事件的对象;evtype是事件类型,不带on前缀;fn是事件处理函数;如果useCapture是true,则事件处理函数在捕获阶段被执行,否则在冒泡阶段执行。
obj.removeEventListener(evtype,fn,useCapture):
W3C提供的删除事件处理函数的方法
attachEvent / detachEvent
obj.attachEvent(evtype,fn):
IE提供的添加事件处理函数的方法。
obj是要添加事件的对象,evtype是事件类型,带on前缀,fn是事件处理函数,IE不支持事件捕获
obj.detachEvent(evtype,fn,):
IE提供的删除事件处理函数的方法,evtype包含on前缀
阻止浏览器默认行为
所有浏览器都支持 :return false;
标准浏览器下:e.preventDefault();
IE浏览器下 :e.returnValue = false;
让a标签失效,不跳转不刷新页面
href:
<a href="javascript:void(0)"></a>
<a href="javascript:;"></a>
css: 在css中添加以下样式,应用到a标签中
.disableCss{
pointer-events:none;
color:#afafaf;
cursor:default
}
jQuery:
1、removeAtttr:
即可使a标签点击上去,完全没有效果
在a标签加属性
style="cursor:pointer"
,移动上去变成手指形状
2、使用jQuery来将a标签置为不可用的方法:
if(boolean){
$("a").attr("disabled", true);
//仅仅为其添加disabled属性只能将其置灰,点击的时候依然会进行跳转
$("a").click(function(){});
}
事件流
三阶段:
1、事件捕获
2、事件目标
3、事件冒泡
iscaptrue为true代表捕获阶段;为false是冒泡阶段;默认是冒泡
事件冒泡、捕获
冒泡:从里往外,事件从里往外发生,点击子元素先执行子元素,再执行父元素
捕获:从外到里,事件从里往外发生,点击子元素先执行父元素,再执行子元素
捕获与冒泡同时存在:先捕获再冒泡,先从外到里,再从里到外
示例
阻止事件冒泡
标准浏览器:e.stopPropagation()
IE:e.cancelBubble = true;
冒泡事件流
当事件在某一DOM元素被触发时,例如用户在客户名字节点上点击鼠标,事件将跟随着该节点继承自的各个父节点冒泡穿过整个的DOM节点层次,直到它遇到依附有该事件类型处理器的节点,此时,该事件是onclick事件。在冒泡过程中的任何时候都可以终止事件的冒泡,在遵从W3C标准的浏览器里可以通过调用事件对象上的stopPropagation()方法,在Internet Explorer里可以通过设置事件对象的cancelBubble属性为true。如果不停止事件的传播,事件将一直通过DOM冒泡直至到达文档根。
捕获事件流
事件的处理将从DOM层次的根开始,而不是从触发事件的目标元素开始,事件被从目标元素的所有祖先元素依次往下传递。在这个过程中,事件会被从文档根到事件目标元素之间各个继承派生的元素所捕获,如果事件监听器在被注册时设置了useCapture属性为true,那么它们可以被分派给这期间的任何元素以对事件做出处理;否则,事件会被接着传递给派生元素路径上的下一元素,直至目标元素。事件到达目标元素后,它会接着通过DOM节点再进行冒泡。
事件委托
后生成元素的事件绑定问题
为解决后生成元素的事件绑定问题:把事件绑定在父元素身上,点击子元素时,通过事件冒泡到父元素身上,判断事件源判定是否是要绑定的元素
//以点击事件为例
oBtn.onclick = function()
{
var oLi = document.createElement('li');
oLi.innerHTML = Math.random();
oUl.appendChild(oLi);
}
oUl.onclick = function(e)
{
e = e || window.event; //兼容问题
var target = e.target;
if(target.tagName == "LI" )
{
console.log(target.innerHTML);
}
}
事件循环
1、所有同步任务都在主线程上执行,形成一个执行栈。
2、主线程之外,还存在一个“任务队列”。只要异步任务有了运行结果,就在“任务队列中放置一个事件”。
3、一旦“执行栈”中的所有同步任务执行完毕,系统就会读取“任务队列”,看看里面有哪些事件,那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
4、主线程不断重复上面的第三步。
任务队列
js是单线程
同步任务:在主线程上排队执行的任务,只有前一个任务完毕,才能执行后一个任务。
异步任务:不进入主线程,而进入“任务队列”的任务,只有“任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
宏任务
1、包括整体代码 script,setTimeout,setInterval
2、宏任务所处的队列就是宏任务队列
3、宏任务队列可以有多个
微任务
1、new Promise(正常执行)Promise.then(回调),process.nextTick(node里的)
2、微任务所处的队列就是微任务队列
3、只有一个微任务队列
4、在上一个宏任务队列执行完毕后,如果有微任务队列就会执行微任务队列中的所有微任务
5、当宏任务队列中的人物执行完后,查看是否有微任务,再执行宏任务
浏览器对象模型 BOM
1、什么是BOM
BOM是Browser Object Model的缩写,浏览器对象模型
BOM提供了独立于内容而与浏览器窗口进行交互的对象
由于BOM主要用于管理窗口与窗口之间的通讯,因此其核心对象是window
BOM由一系列相关的对象构成,并且每个对象都提供了很多方法与属性
2、BOM的作用
BOM提供了一些访问窗口对象的一些方法,我们可以用它来移动窗口位置,改变窗口大小,打开新窗口和关闭窗口,弹出对话框,进行导航以及获取客户的一些信息如:浏览器品牌版本,屏幕分辨率。
BOM最强大的功能是它提供了一个访问HTML页面的一入口——document对象,以使得我们可以通过这个入口来使用DOM的强大功能!!!
window对象
1、window对象是BOM的顶层(核心)对象,所有对象都是通过它延伸出来的,也可以称为window的子对象。
2、由于window是顶层对象,因此调用它的子对象时可以不显示的指明window对象,
如:document.write(“BOM”); 即:window.document.write(“BOM”);
3、window对象是BOM中所有对象的核心。window对象表示整个浏览器窗口,但不必表示其中包含的内容。此外,window还可用于移动或调整它表示的浏览器的大小,或者对它产生其他影响。
4、所有全局 JavaScript 对象,函数和变量自动成为 window 对象的成员:全局变量是 window 对象的属性;全局函数是 window 对象的方法。
窗口尺寸
两个属性可用用于确定浏览器窗口的尺寸:
window.innerHeight - 浏览器窗口的内高度(以像素计)
window.innerWidth - 浏览器窗口的内宽度(以像素计)
//显示浏览器窗口的高度和宽度:(不包括工具栏和滚动条)
var w = window.innerWidth|| document.documentElement.clientWidth|| document.body.clientWidth;
var h = window.innerHeight|| document.documentElement.clientHeight|| document.body.clientHeight;
其他方法
新建窗体
window.open():打开(弹出)一个新的窗体,window.open(url, name, features, replace);
url – 要载入窗体的URL
name – 新建窗体的名称(目标,将在a 标签的target属性中用到,当与已有窗体名称相同时将覆盖窗体内容).open函数默认的打开窗体的方式为target的_blank弹出方式,因此页面都将以弹出的方式打开
features – 代表窗体特性的字符串,字符串中每个特性使用逗号分隔
replace – 一个布尔值,说明新载入的页面是否替换当前载入的页面,此参数通常不用指定
window.close() - 关闭当前窗口
window.moveTo() -移动当前窗口
window.resizeTo() -重新调整当前窗口
窗体控制(不常用)
moveBy(x,y):从当前位置水平移动窗体x个像素,垂直移动窗体y个像素,x为负数,将向左移动窗体,y为负数,将向上移动窗体。
moveTo(x,y):移动窗体左上角到相对于屏幕左上角的(x,y)点,当使用负数做为参数时会把窗体移出屏幕的可视区域。
resizeBy(w,h):相对窗体当前的大小,宽度调整w个像素,高度调整h个像素。如果参数为负值,将缩小窗体,反之扩大窗体。
resizeTo(w,h):把窗体宽度调整为w个像素,高度调整为h个像素。
窗体滚动轴控制
scrollTo(x,y):在窗体中如果有滚动条,将横向滚动条移动到相对于窗体宽度为x个像素的位置,将纵向滚动条移动到相对于窗体高度为y个像素的位置。
scrollBy(x,y):如果有滚动条,将横向滚动条移动到相对于当前横向滚动条的x个像素的位置(就是向左移动x像素),将纵向滚动条移动到相对于当前纵向滚动条高度为y个像素的位置(就是向下移动y像素)。
窗体焦点控制
focus():使窗体或控件获取焦点
blur():使窗体或控件失去焦点
window.history 对象
window.history 对象:包含浏览器历史
1、属性
属性 | 描述 |
---|---|
length | 返回浏览器历史列表中的 URL 数量 |
2、方法
history.back() - 加载历史列表中前一个 URL,等同于在浏览器点击后退按钮
history.forward() - 加载历史列表中下一个 URL,等同于在浏览器中点击前进按钮
history.go(num) - 加载 history 列表中的某个具体页面
num正数:下num个历史记录
num负数:上num个历史记录
window.location 对象
与地址栏有关
1、属性
属性 | 描述 |
---|---|
hash | 设置或返回从井号 (#) 开始的 URL(锚),和id配合跳转 |
host | 设置或返回主机名和当前 URL 的端口号 |
hostname | 设置或返回当前 URL 的主机名 |
href | 设置或返回完整的 URL |
pathname | 设置或返回当前 URL 的路径部分 |
port | 设置或返回当前 URL 的端口号 |
protocol | 设置或返回当前 URL 的协议 |
search | 设置或返回从问号 (?) 开始的 URL(查询部分) |
window.navigator 对象
window.navigator 对象:包含有关访问者的信息
属性 | 描述 |
---|---|
userAgent | 返回由浏览器发送到服务器的用户代理报头(user-agent header) |
cookieEnabled | 如果 cookie 已启用,返回 true;否则返回 false |
appName | 返回浏览器的应用程序名称 |
appCodeName | 返回浏览器的应用程序代码名称 |
product | 返回浏览器引擎的产品名称 |
appVersion | 返回有关浏览器的版本信息 |
platform | 返回浏览器平台(操作系统) |
language | 返回浏览器语言 |
onLine | 假如浏览器在线,返回 true |
javaEnabled() 方法:如果 Java 已启用,返回 true
window.screen 对象
window.screen 对象:包含用户屏幕的信息
1、属性
属性 | 描述 |
---|---|
screen.width | 返回以像素计的访问者屏幕宽度 |
screen.height | 返回以像素计的访问者屏幕的高度 |
screen.availWidth | 返回访问者屏幕的宽度,以像素计,减去诸如窗口工具条之类的界面特征 |
screen.availHeight | 返回访问者屏幕的高度,以像素计,减去诸如窗口工具条之类的界面特征 |
screen.colorDepth | 返回用于显示一种颜色的比特数 |
screen.pixelDepth | 返回屏幕的像素深度 |
document 对象
document对象是BOM的一部分,同时也是HTML DOM的HTMLDocument对象的一种表现形式,反过来说,它也是XML DOM Document对象。
JavaScript中的大部分处理DOM的过程都利用document对象,所以我们访问文档需要使用BOM提供的这个入口
cookie
Cookie 是在您的计算机上存储在小的文本文件中的数据。当 web 服务器向浏览器发送网页后,连接被关闭,服务器会忘记用户的一切。Cookie 是为了解决“如何记住用户信息”而发明的:当用户访问网页时,他的名字可以存储在 cookie 中,下次用户访问该页面时,cookie 会“记住”他的名字。
Cookie 保存在名称值对中,当浏览器从服务器请求一个网页时,将属于该页的 cookie 添加到该请求中。这样服务器就获得了必要的数据来“记住”用户的信息。
要求:浏览器不能关闭本地 cookie 支持
document.cookie 属性
1、创建 cookie
您还可以添加有效日期(UTC 时间)。默认情况下,在浏览器关闭时会删除 cookie:
通过 path 参数,您可以告诉浏览器 cookie 属于什么路径。默认情况下,cookie 属于当前页。
2、读取 cookie
document.cookie 会在一条字符串中返回所有 cookie,比如:cookie1=value; cookie2=value; cookie3=value;
3、改变cookie
旧 cookie 被覆盖:
4、删除 cookie
删除 cookie 时不必指定 cookie 值:直接把 expires 参数设置为过去的日期即可:
要求:应该定义 cookie 路径以确保删除正确的 cookie,如果不指定路径,一些浏览器不会让你删除 cookie。
window.frames 对象
windows.frames对象:返回窗口中所有命名的框架。
该集合是 Window 对象的数组,每个 Window 对象在窗口中含有一个框架或 。属性 frames.length 存放数组 frames[] 中含有的元素个数。
注意:frames[] 数组中引用的框架可能还包括框架,它们自己也具有 frames[] 数组。
三种类型的弹出框
window.alert() 警告框
如果要确保信息传递给用户,通常会使用警告框。
当警告框弹出时,用户将需要单击“确定”来继续
window.confirm() 确认框
如果您希望用户验证或接受某个东西,则通常使用“确认”框。
当确认框弹出时,用户将不得不单击“确定”或“取消”来继续进行。
如果用户单击“确定”,该框返回 true。如果用户单击“取消”,该框返回 false。
window.prompt() 提示框
如果您希望用户在进入页面前输入值,通常会使用提示框。
当提示框弹出时,用户将不得不输入值后单击“确定”或点击“取消”来继续进行。
如果用户单击“确定”,该框返回输入值。如果用户单击“取消”,该框返回 NULL。
折行
如需在弹出框中显示折行,请在反斜杠后面加一个字符 n
定时事件( Timing Events)
window 对象允许以指定的时间间隔执行代码,这些时间间隔称为定时事件。
通过 JavaScript 使用的有两个关键的方法:
1、
setTimeout(function, milliseconds)
:在等待指定的毫秒数后执行函数。
2、
setInterval(function, milliseconds)
:等同于 setTimeout(),但持续重复执行该函数。
setTimeout() 和 setInterval() 都属于 HTML DOM Window 对象的方法
window.setTimeout()
暂停指定的毫秒数后执行指定的代码
第一个参数是要执行的函数,第二个参数指示执行之前的毫秒数。
clearTimeout() 方法停止执行setTimeout() 中规定的函数
window.setInterval()
在每个给定的时间间隔重复给定的函数
第一个参数是要执行的函数(回调函数),第二个参数每个执行之间的时间间隔的长度。
clearInterval() 方法停止 setInterval() 方法中指定的函数的执行
文档对象模型 DOM
Document Object Model (DOM)是HTML和XML文档的编程接口。它提供了上述文档的一种结构化表示,同时也定义了一种通过程序来改变文档结构,风格,以及内容的方式。DOM用一组结构化的节点以及对象来表示文档。本质上就是将网页和脚本语言以及编程语言连接起来。
一个网页是一个文档。这个文档可以被显示在浏览器窗口中,也可以以html源码的形式显示。这两中情况中,文档都是同一个。DOM提供了另一种方式来表示,存储,操作这个文档。DOM是网页的一种完全的面向对象的表示方法,可以通过脚本语言(比如说JavaScript)来改变。
W3C DOM标准形成了当今大多数浏览器的DOM基础。许多浏览器提供超出W3C标准的扩展,所以当用在可能被拥有不同DOM的各种浏览器使用的场合时 一定要多加注意
DOM标准主要要为:微软DOM与W3C DOM,一般IE实现的是微软DOM,而其它浏览器则不同程度的实际了W3C DOM
DOM编程界面
在 DOM 中,所有 HTML 元素都被定义为对象。
编程界面是每个对象的属性和方法。
属性:能够获取或设置的值(就比如改变 HTML 元素的内容)
.innerHTML: 设置或返回表格行的开始和结束标签之间的 HTML。
oDiv1.innerHtml = "<h2>ha</h2>";
//输出结果:ha (以h2样式显示)
.innerText: 不能识别HTML,只能输出“ ”中的文本内容
oDiv1.innerText = "<h2>ha</h2>";
//输出结果:<h2>ha</h2>
方法:能够完成的动作(比如添加或删除 HTML 元素)
获取元素的常用方法
1、document.getElementById 通过id 获取元素 返回查找的dom对象
在一个文档中id必须是唯一的,getElementById方法只会返回一个元素
var p1 = document.getElementById("p1");
//获取ID为p1的那个元素
2、document.getElementsByTagName 通过标签 获取元素 返回数组 数组中存放的是dom 对象 没取到时返回空数组,因为页面中标签相同的元素很多,所以即使页面中只有一个需要获取的元素getElementsByTagName也会返回一个集合
var allP = document.getElementsByTagName("p");
//获取文档中所有p标签
3、document.getElementsByClassName 通过class名获取元素 返回数组 数组中存放的是dom 对象 dom3版本 ie6不支持该方法
兼容——封装函数:
function getElementsByClass(clsName)
{
// 取到页面中所有的元素
var result = [];
var allELe = document.getElementsByTagName("*");
for(var i=0; i<allELe.length; i++){
// class 是保留字 用className取到class名
//"a b" == "a"
//"a b c" == ["a","b","c"] 通过split方法将字符串分隔成数组
var arr = allELe[i].className.split(" "); //["a","b"]
for(var k=0; k<arr.length; k++){
//判断class名==传进来的clsName push到数组
if(arr[k] == clsName){
result.push(allELe[i]);
}
}
}
return result;
}
var a2 = getElementsByClass('a');
4、document.getElementsByName 返回数组 表单元素 name属性 后台使用
节点
类型
共12种节点类型:
Node.ELEMENT_NODE (1) 【元素节点】
Node.ATTRIBUTE_NODE (2) 【属性节点 (id)】
Node.TEXT_NODE (3)【文本节点】
Node.CDATA_SECTION_NODE (4)
Node.ENTITY_REFERENCE_NODE (5)
Node.ENTITY_NODE (6)
Node.PROCESSING_INSTRUCTION_NODE (7)
Node.COMMENT_NODE (8) 【注释节点】
Node.DOCUMENT_NODE (9)
Node.DOCUMENT_TYPE_NODE (10)
Node.DOCUMENT_FRAGMENT_NODE (11)
Node.NOTATION_NODE (12)
节点属性
1、nodeType
返回值类型: Number
节点类型:oDiv.firstChild.nodeType
元素节点———— 1
属性节点———— 2
文本节点———— 3
注释节点———— 8
2、nodeName
返回值类型:String
节点的名字:根据节点的类型而定义
元素节点返回tagName,
文本节点返回#text,
属性节点返回属性名
3、nextSibling
返回值类型:node
指向后一个兄弟节点;如果这个节点就是最后一个兄弟节点,那么该值为null
.extSibling在IE6中可以找到下一个兄弟, 在标准浏览器下会找到回车+空格
.nextElementSibling —— dom3的语法 存在兼容性问题 IE6以下不兼容
4、previousSibling
返回值类型:node
指向前一个兄弟节点;如果这个节点就是第一个兄弟节点,那么该值为null
previousElementSibling —— dom3
5、firstChild
返回值类型:node
指向在childNodes列表中的第一个节点 firstElementChild
6、lastChild
返回值类型:node
指向在childNodes列表中的最后一个节点 lastElementChild
7、children
所有浏览器都支持
节点的操作(方法)
1、createElement()
2、appendChild(node):将node添加到childNodes的末尾
3、removeChild(node):从childNodes中删除node
4、replaceChild (newnode,oldnode):将childNodes中的oldnode替换成newnode
5、insertBefore (newnode,refnode):在childNodes中的refnode之前插入newnode
6、cloneNode(true):使用参数true表示克隆节点时包含子节点
7、.setAttribute(“属性名”,“属性值”) :设置属性
8、.getAttribute(“属性名”):获取属性(获取属性名对应的属性值)
获取设置样式
1、可以获取也可以设置,获取到的是内联样式
elem.style.width
2、只能获取,不能设置
取到包括width(内容)+padding+border不包括margin
elem.offsetWidth
3、最近已定位的祖先元素
elem.offsetParent
4、相对于最近已定位的祖先元素,如果没有相对于 body
动画
animate(oDiv,{
width:500
},function(){
alert("哈哈");
})
jQuery
jQuery 是一个高效、精简并且功能丰富的 JavaScript 工具库。
jQuery教程
jq底层原理
1、 $() 是一个函数, 返回值jq对象
2、 jQuery是一个类,在这个类的原形下有许多jq自定义的方法.每次调用$返回一个新的jq对象,同时在$函数中根据传入参数的类型、函数或者字符串。
3、把选中的元素存在数组中,遍历这个数组,取出每个元素进行dom操作。真正的DOM中查找遍历的操作是在构造函数里面进行的,将查到的元素存到this.elements[i]数组里,对数组的元素进行遍历,进行绑定事件。
4、在每一个方法中:
return this
,this就是在$函数中返回的jq对象。
文档就绪函数
等页面的(HTML)结构加载执行
执行比 window.onload 快
写多个时不会发生后面的覆盖前面的
$(document).ready(function(){
$("#div1").css("background","green");
})
//存在简写方式
$(function(){
$("#div1").css("background","green");
})
获取jQuery 对象
没有原生对象(.style.background)的方法,使用.css()方法
$div = $('#div1');
$div.css('background','#ff0036');
与原生对象转化
1、把jQuery对象 转化成原生对象
$div.get(0);
$div[0];
2、把原生对象转化成jQuery对象
修改HTML内容:
jQuery 选择器
1、后代选择器
2、群组选择器
属性 / CSS
1、属性
.attr()——设置普通属性
.prop()——指定某些元素特有的属性
.removeAttr()
2、CSS
.addClass()
事件
事件绑定
后生成元素事件绑定
$("ul").on("click","li",function (){
console.log( $(this).html() );
})
自动获取焦点
$("#test").on("focus",function(){
$(this).css("background","pink");
})
$("#text").trigger("focus");
//跟鼠标点上去情况一样
//triggerHandler——只会执行处理函数
鼠标事件
mouseenter——不支持冒泡
mouseover——支持冒泡
jQuery简单仿写
function getStyle(elem, prop) {//样式
if (elem.currentStyle) {
return elem.currentStyle[prop];
} else if (getComputedStyle) {
return getComputedStyle(elem, false)[prop];
} else {
return elem.style[prop];
}
}
function addEvent(elem, type, handler) {//事件
if (elem.addEventListener) {
elem.addEventListener(type, handler, false);
} else if (elem.attachEvent) {
elem.attachEvent('on' + type, handler)
} else {
elem['on' + type] = handler;
}
}
function $(args) {
return new MyJQuery(args);
}
function MyJQuery(args) {
this.elements = [];
switch (typeof args) {//判断传值类型
case 'function':
addEvent(window, 'load', args);
break;
case 'string':
var firstLetter = args.charAt(0);
switch (firstLetter) {
case '#': //#xxx
this.elements.push(document.getElementById(args.substring(1)));
break;
case '.':
this.elements = document.getElementsByClassName(args.substring(1));
break;
default:
this.elements = document.getElementsByTagName(args);
}
break;
case 'object':
this.elements.push(args);
break;
}
}
MyJQuery.prototype.addClass = function (clsName) {
for (var i = 0; i < this.elements.length; i++) {
var re = new RegExp('\\b' + clsName + '\\b', 'g');//边界,取出原来的 classname
if (!re.test(this.elements[i].className)) {
this.elements[i].className += ' ' + clsName;
this.elements[i].className = MyJQuery.trim(this.elements[i].className);
//去空格
}
}
return this;
};
MyJQuery.prototype.width = function (length) {
if (length) {
for (var i = 0; i < this.elements.length; i++) {
this.elements[i].style.width = length + 'px';
}
return this;
}
return getStyle(this.elements[0], 'width');
};
MyJQuery.prototype.click = function (fn) {
for (var i = 0; i < this.elements.length; i++) {
addEvent(this.elements[i], 'click', fn);
}
return getStyle(this.elements[0], 'width');
};
MyJQuery.prototype.click = function (fn) {
for (var i = 0; i < this.elements.length; i++) {
addEvent(this.elements[i], 'click', fn);
}
return this;
};
MyJQuery.prototype.on = function (type, selector, fn) {
,click,'.l',function(){}
if (typeof selector == 'string') {
for(var i=0; i<this.elements.length; i++){
addEvent(this.elements[i], type, function (e) {
e = e || window.event;
var target = e.target || e.srcElement;
switch (selector.charAt(0)){
case '#':
break;
case '.':
if(target.className == selector.substr(1)){
fn.apply(target);//改变this指向,指向真实绑定的元素
}
break;
default: break;
}
});
}
} else {
for (var i = 0; i < this.elements.length; i++) {
addEvent(this.elements[i], type, fn);
}
}
return this;
};
MyJQuery.prototype.siblings = function (selector) {
var result = [];
for (var i = 0; i < this.elements.length; i++) {
var childs = this.elements[i].parentNode.children;
for(var j=0; j<childs.length; j++){
switch (selector.charAt(0)){
case '#':
break;
case '.':
if(childs[j].className == selector.substr(1)){
if(childs[j] != this.elements[i] && result.indexOf(childs[j]) == -1){
result.push(childs[j]);
}
}
break;
default: break;
}
}
}
return result;
};
MyJQuery.prototype.css = function (prop, value) {
if(value){
for (var i = 0; i < this.elements.length; i++) {
this.elements[i].style[prop] = value;
}
} else {
if (typeof prop == 'string'){
return getStyle(this.elements[0], prop);
} else if(typeof prop == 'object'){
for(var p in prop){ //p:background-color=>backgroundColor
p = p.replace(/\-[a-z]/g, function (word) {
return word.substring(1).toUpperCase();
}
);
for (var i = 0; i < this.elements.length; i++) {
this.elements[i].style[p] = prop[p];
}
}
}
}
};
MyJQuery.trim = function (str) {
var re = /^\s+|\s+$/g; // _abc_ return str.replace(re, '');
};
AJAX
AJAX的优点:
<1>.无刷新更新数据:在无需重新加载整个网页的情况下,能够更新部分网页的技术。
<2>.异步与服务器通信:客户端与服务器端异步的通信的技术
AJAX原理/原生AJAX
创建 XMLHttpRequest 对象,有兼容性问题
var xmlhttp;
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
向服务器发送请求
XMLHttpRequest 对象的 open() 和 send() 方法:
① open(method,url,async):
method: 请求的类型:GET 或 POST
url: 文件在服务器上的位置
async: true(异步)或 false(同步)
② send(string):仅用于 POST 请求
get 请求方式: url 是否异步
xmlhttp.open("GET", "test1.txt?name=zs", true);
xmlhttp.send();
post 请求方式 :请求地址 url 是否异步
xmlhttp.open("POST","ajax_test.asp",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Bill&lname=Gates");
get 和 post 区别:
get — 请求 / post — 提交
get 数据量小(IE:2-4k) / post 向服务器发送大量数据(POST 没有数据量限制)
get 放在地址栏,不安全 / post 放在包体里,相对安全
get 可以缓存 / post 无法使用缓存文件(更新服务器上的文件或数据库)
get 一般用于获取数据 / post 一般用于表单提交
在发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
服务器响应
XMLHttpRequest 对象的 responseText属性 :获得字符串形式的响应数据
或 responseXML属性:获得XML形式的响应数据。
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
console.log(xmlhttp.responseText); //取到返回来的数据
}
}
当请求被发送到服务器时,我们需要执行一些基于响应的任务。
每当 readyState 改变时,就会触发 onreadystatechange 事件。
readyState 属性存有 XMLHttpRequest 的状态信息。
readyState — >XMLHttpRequest 的状态
从 0 到 4 发生变化:
0 - (请求未初始化) 还没有调用send()方法
1 - (正在加载,服务器连接已建立) 已调用send()方法,正在发送请求
2 - (加载完成,请求已接收) send()方法执行完成
3 - (交互,请求处理中) 正在解析响应内容
4 - (请求已完成,且响应已就绪) 响应内容解析完成,可以在客户端调用了
status 状态码:
status属性返回当前请求的http状态码,此属性仅当数据发送并接收完毕后才可获取。
1、100-199 用于指定客户端应相应的某些动作。
2、200-299 用于表示请求成功。
3、300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息。
4、400-499 用于指出客户端的错误。
5、500-599 用于支持服务器错误。
200 (“OK”) 成功 一切正常,对GET和POST请求的应答文档跟在后面,读取response
500 服务器方面的问题
503 (服务不可用)
404 找不到资源
301 永久重定向
302 临时重定向
304 缓存
完整的HTTP状态码如下:
- 100 Continue 初始的请求已经接受,客户应当继续发送请求的其余部分
- 101 Switching Protocols 服务器将遵从客户的请求转换到另外一种协议
- 200 OK 一切正常,对GET和POST请求的应答文档跟在后面。
- 201 Created 服务器已经创建了文档, Location头给出了它的URL。
- 202 Accepted 已经接受请求,但处理尚未完成。
- 203 Non-Authoritative Information 文档已经正常地返回,但一些应答头可能不正确,因为使用的是文档的拷贝
- 204 No Content 没有新文档,浏览器应该继续显示原来的文档。如果用户定期地刷新页面,而Servlet可以确定用户文档足够新,这个状态代码是很有用的
- 205 Reset Content 没有新的内容,但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容
- 206 Partial Content 客户发送了一个带有Range头的GET请求,服务器完成了它
- 300 Multiple Choices 客户请求的文档可以在多个位置找到,这些位置已经在返回的文档内列出。如果服务器要提出优先选择,则应该在Location应答头指明。
- 301 Moved Permanently 客户请求的文档在其他地方,新的URL在Location头中给出,浏览器应该自动地访问新的URL。
- 302 Found 类似于301,但新的URL应该被视为临时性的替代,而不是永久性的。
- 303 See Other 类似于301/302,不同之处在于,如果原来的请求是POST, Location头指定的重定向目标文档应该通过GET提取
- 304 Not Modified 客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。
- 305 Use Proxy 客户请求的文档应该通过Location头所指明的代理服务器提取
- 307 Temporary Redirect 和302(Found)相同。许多浏览器会错误地响应302应答进行重定向,即使原来的请求是POST,即使它实际上只能在POST请求的应答是303时才能重定向。由于这个原因, HTTP 1.1新增了307,以便更加清除地区分几个状态代码:当出现303应答时,浏览器可以跟随重定向的GET和POST请求;如果是307应答,则浏览器只能跟随对GET请求的重定向。
- 400 Bad Request 请求出现语法错误。
- 401 Unauthorized 客户试图未经授权访问受密码保护的页面。应答中会包含一个WWW-Authenticate头,浏览器据此显示用户名字/密码对话框,然后在填写合适的Authorization头后再次发出请求。
- 403 Forbidden 资源不可用。
- 404 Not Found 无法找到指定位置的资源
- 405 Method Not Allowed 请求方法(GET、 POST、 HEAD、 Delete、 PUT、 TRACE等)对指定的资源不适用。
- 406 Not Acceptable 指定的资源已经找到,但它的MIME类型和客户在Accpet头中所指定的不兼容
- 407 Proxy Authentication Required 类似于401,表示客户必须先经过代理服务器的授权。
- 408 Request Timeout 在服务器许可的等待时间内,客户一直没有发出任何请求。客户可以在以后重复同一请求。
- 409 Conflict 通常和PUT请求有关。由于请求和资源的当前状态相冲突,因此请求不能成功。
- 410 Gone 所请求的文档已经不再可用,而且服务器不知道应该重定向到哪一个地址。它和404的不同在于,返回407表示文档永久地离开了指定的位置,而404表示由于未知的原因文档不可用。
- 411 Length Required 服务器不能处理请求,除非客户发送一个Content-Length头
- 412 Precondition Failed 请求头中指定的一些前提条件失败
- 413 Request Entity Too Large 目标文档的大小超过服务器当前愿意处理的大小。如果服务器认为自己能够稍后再处理该请求,则应该提供一个Retry-After头
- 414 Request URI Too Long URI太长
- 416 Requested Range Not Satisfiable 服务器不能满足客户在请求中指定的Range头
- 500 Internal Server Error 服务器遇到了意料不到的情况,不能完成客户的请求
- 501 Not Implemented 服务器不支持实现请求所需要的功能。例如,客户发出了一个服务器不支持的PUT请求
- 502 Bad Gateway 服务器作为网关或者代理时,为了完成请求访问下一个服务器,但该服务器返回了非法的应答
- 503 Service Unavailable 服务器由于维护或者负载过重未能应答。例如, Servlet可能在数据库连接池已满的情况下返回503。服务器返回503时可以提供一个Retry-After头
- 504 Gateway Timeout 由作为代理或网关的服务器使用,表示不能及时地从远程服务器获得应答
- 505 HTTP Version Not Supported 服务器不支持请求中所指明的HTTP版本
优点
1、无刷新更新数据。
2、异步与服务器通信。
3、前端和后端负载平衡。(减轻服务器的负担,AJAX的原则是“按需取数据”, 可以最大程度的减少冗余请求和响应对服务器造成的负担)
4、基于标准被广泛支持。
5、界面与应用分离。
缺点
1、AJAX没有Back和History功能,即对浏览器机制的破坏。
2、AJAX的安全问题。
3、违背URL和资源定位的初衷。
4、客户端过肥,太多客户端代码造成开发上的成本。
在浏览器地址栏里输入一个地址回车
1、浏览器会发送一个get请求,该请求会被转发到DNS服务器,由DNS服务器解析域名,然后再转发到相应的IP地址对应的服务器。
2、在服务器端由Apache这样的Web Server来接收请求,并进行相应的处理,然后 响应结果给客户端浏览器。
3、浏览器接收响应的结果,并进行相应的语法检查,如果有错误,可能会提示错 误,如果没有错误,就进行渲染。
4、渲染的时候先生成DOM树,然后根据CSS和JS规则生成渲染树(渲染树中的结构 往往比DOM树要少,因为有些DOM树中有些元素如果隐藏的话,不会出现在渲染树 中),最后再渲染出来。
ES6
作用域
es5 只有全局作用域、函数作用域(var)
es6 新增块级作用域
声明
const 命令
const 命令声明一个只读的常量。一旦声明,常量的值就不能改变。 实际上保证的是变量指向的那个内存地址不得改动 。
对于引用数据类型(对象 / 数组)来说:地址不能修改,值可以修改;
让引用类型的值也不能修改:
Object.freeze(obj);
let 命令
let 命令声明变量,所声明的变量一定要在声明后使用,否则报错。
①不存在变量提升 ②不允许重复声明 ③块级作用域 ④暂时性死区(从函数体开始到定义之前)
let 与 var 的区别
1、let 不存在变量提升 var存在变量提升
2、let 块级作用域:let 所声明的变量,只在let命令所在的代码块内有效。
3、let 不能重复声明变量
let a = 10;
let a = 20; // [❌]
let a = 10;
var a = 20; // [❌]
4、let 暂时性死区 (临时失效区):在当前作用域不允许有同名的变量进来
let a = 5;
function fn(){
console.log(a); //var存在变量提升
var a = 10;
} //undefined
let a = 5;
function fn(){
console.log(a); //let不存在变量提升
let a = 10;
} // [❌] a is not defined
let a = 5;
function fn(){
let a = 10;
console.log(a); //输出:10
}
var a = 5;
function fn(){
let a = 10;
console.log(a);
} //输出:10
let c = 10;
function fn(){
console.log(c); // 输出:10
c = 30; //
console.log(c); // 输出:30
}
变量的解构赋值
1、数组解构
let arr = [1,2];
let [a,b] = arr;
console.log(a,b); //输出:1 2
2、对象解构
//变量名与属性名相同,顺序无关
let p1 = {
name:"zs",
age:20
}
let {name ,age} = p1;
console.log(name,age);
//重命名 改变变量名
let p1 = {
name:"zs",
age:20
}
let {name ,age:n} = p1;
console.log(name,n);
3、字符串解构
对象扩展
对象的属性和方法的简写方式
属性名与变量名 同名
属性名 存在 变量中 [变量名]
方法的简写
新增的方法
Object.is()
比较两个值是否严格相等
与严格比较运算符(===)的行为基本一致
//特殊情况:
NaN === NaN // false
Object.is(NaN,NaN) // true
+0 === -0 // true
Object.is(+0,-0) // false
symbol 增加的基本数据类型
let name = Symbol();
obj[name] = ‘XX';
// 该属性不会出现在for...in、for...of循环中
箭头函数 =>
箭头函数:定义匿名函数;可以改变有些函数的this指向
this 指向
this 指的是声明时的this:父作用域中的this(在父作用域中声明)
普通函数:this 指的是调用时的this
箭头函数不能用于构造函数
不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
箭头函数中不能使用arguments(类数组)
箭头函数不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
运算符
rest 运算符
let a = (x, ...rest) => {
console.log(x, rest); // 1 (2) [2, 3]
}
a(1,2,3);
//普通函数:
function a(x, y, z) {
console.log(x, y, z); // 1 2 3
console.log(arguments);
//Arguments(3) [1, 2, 3, callee: f, Symbol(Symbol.iterator):f ]
console.log(arguments.callee()); //调用自己
}
a(1, 2, 3);
… 扩展运算符
1、复制数组
2、把一个数组作为另一个数组的一部分
3、合并数组 、 对象
4、类数组转化为数组
let a = (...rest) => {
console.log(rest); // (3) [1, 2, 3]
}
a(1,2,3);
set()
1、Set函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化
2、set也可以用来去重
var set = new Set([1, 2, 3, 4, 4]);
[...set]
// [1, 2, 3, 4]
3、4个方法
• add(value):添加某个值,返回Set结构本身。
• delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
• has(value):返回一个布尔值,表示该值是否为Set的成员。
• clear():清除所有成员,没有返回值
4、遍历其中元素用 for…of…
map()
1、相比于set的方法,map新增了set 和 get方法
let ar=new Map(); //键值对
ar.set('key','value'); //key也可以是变量或者对象
console.log(ar.get('key'));
2、可用的方法
实例属性和方法:size、set、get、has、delete、clear
Promise
Promise对象: 代表了未来某个将要发生的事件(通常是一个异步操作)
- 有了promise对象, 可以将异步操作以同步的流程表达出来, 避免了层层嵌套的回调函数(俗称’回调地狱’)
- ES6的Promise是一个构造函数, 用来生成promise实例
使用的2个步骤
// 创建promise对象
let promise = new Promise((resolve, reject) => {
//初始化promise状态为 pending
//执行异步操作
if(异步操作成功) {
resolve(value);
//修改promise的状态fullfilled
} else {
reject(errMsg);
//修改promise的状态为rejected
}
})
//调用promise的then()
promise.then(function(
))
Promise 对象的三个状态
- pending: 初始化状态
- fullfilled: 成功状态
-
rejected: 失败状态
把异步的操作以同步的流程表示出来
resolve成功回调函数 =>then
失败调用reject() => catch/then第二个回调函数
generator
1、ES6提供的解决异步编程的方案之一
2、Generator函数是一个状态机,内部封装了不同状态的数据,
3、用来生成遍历器对象
4、可暂停函数(惰性求值), yield可暂停,next方法可启动。每次返回的是yield后的表达式结果
特点
1、function 与函数名之间有一个星号
2、内部用yield表达式来定义不同的状态
function* generatorExample(){
let result = yield 'hello'; // 状态值为hello
yield 'generator'; // 状态值为generator
}
3、generator函数返回的是指针对象,而不会执行函数内部逻辑
4、调用next方法函数内部逻辑开始执行,遇到yield表达式停止,返回{value: yield后的表达式结果/undefined, done: false/true}
5、再次调用next方法会从上一次停止时的yield处开始,直到最后
6、yield语句返回结果通常为undefined, 当调用next方法时传参内容会作为启动时yield语句的返回值。
ES7 :async函数 await 异步回调
真正意义上去解决异步回调的问题,同步流程表达异步操作
本质:Generator的语法糖
语法
async function foo(){
await 异步操作;
await 异步操作;
}
async function firstReq(){
return new Promise(function(resolve){
setTimeout(() => {
resolve()
}, 2000);
})
}
async function asyncPrint(){
console.log('开始');
await firstReq();
console.log('第一个请求完成');
}
asyncPrint();
特点
1、不需要像Generator去调用next方法,遇到await等待,当前的异步操作完成就往下执行
2、返回的总是Promise对象,可以用then方法进行下一步操作
3、async取代Generator函数的星号*,await取代Generator的yield
4、语意上更为明确,使用简单,经临床验证,暂时没有任何副作用
defer和async
都能实现异步加载、延迟加载js
defer 是IE中支持的语法,defer 加载时可以几个文件都异步加载,等dom结构渲染完(页面解析完毕) 都加载完再执行,理论上可以保证文件加载顺序。
async 等文件加载完之后立即执行,不能保证文件加载顺序