JavaScript
-
简介:JavaScript是在浏览器中解释运行的脚本语言,用来给HTML网页增加动态功能。
-
JS的组成
- ECMAScript
- DOM 页面元素
- BOM 浏览器元素
API程序应用接口
JS的引入方式
- 内部引入
- 外部引入
- 行内引入
API和Web API总结
- API是为我们程序员提供的一个接口,帮助我们实现某种功能,我们会使用就可以了,不必纠结内部何实现
- Web API主要是针对于浏览器提供的接口,主要针对于浏览器做交互效果。
- Web API 一般都有输入和输出(函数的传参和返回值) , Web API很多都是方法(函数)
- 学习Web API可以结合前面学习内置对象方法的思路学习
如果哪一个script标签用于引入外部js文件了,那么浏览器会忽略掉该标签内部所有的js代码(如果有的话)
暂且需要记住的测试方法
- window.alert(exp) 输出到警告框
- console.log(exp) 输出到控制台
- document.write(exp) 输出到页面
- id.innerHTML= 改变某一个元素的开始标签与结束标签之间的内容
标识符:变量,对象的属性以及函数的名字。以数字,英文字母,_和$组成,其中数字不能作为开头。
变量:存储数据的容器。
- 变量的命名规则 var 变量名;
- 命名规则
- 首先只能由数字、字母、下划线、以及$构成。
- 其次首字母不能为数字
- 最后不能和已有关键字和库函数同名
- 不成文的命名规则
- 变量名必须用英文,不能用拼音。
- 见名知意
- 驼峰命名法:除了第一个单词之外的单词,首字母大写。
- 变量不应该重复定义
- 命名规则
// 声明了一个变量并且往里塞了一个值
// var 变量名 = 值;
var a1 = 5;
// 声明了一个变量但不赋值,此时这个变量里面存的是空值(undefined)
// var 变量名;
var a2;
常量:值本身。
!表达式:一段具有返回值(计算结果)的语句。任何拥有返回值的语句都是表达式,反之也是成立的。
运算符:将简单表达式组合成复杂表达式的方法。
!数据类型:
检验算法合法性的必要条件
-
基本类型:
- undefind:未被赋值的变量
- null:空值 可以和undefind一样理解
- number(数字):
- 1,-1,0,
- NaN(not a number),
- Infinity(无限),
- -Infinity(负无限)
- 整型——没有小数点的数字
- 浮点型——有小数点的数字
- string:字符串类型——被单引号或双引号引起来的字符 “heihei” ‘hahaha’
- boolean: 布尔类型——逻辑值
- true-成立
- false-不成立
-
引用类型:将Object赋值给变量a时,a引用的是Object的地址(快捷方式)
- object(对象):{属性名:属性值,属性名:属性值}
- function(函数)
- typeof 可以使用 typeof 关键字查看变量类型
<script> var a; console.log(typeof(a)); </script>
!表达式的副作用:如果某个表达式它的存在与否对我们整个js执行环境上下文有不同的运算结果时,我们称这个表达式是含有副作用的表达式。比如最常见的变量声明语句,这就是一个含有副作用的表达式。
数值的操作方法:
- parseInt(Number) 取整
- parseFloat(Number) 强制转换为数字
- Number.toFixed(保留的位数) 保留几位小数;
注意:返回结果不再是Number类型而是字符串。
运算符:将简单表达式组合成复杂表达式的方法。
三要素:优先级 结合方向 操作目数
- 算数运算符
- 赋值运算符
- 自增自减运算符
- 关系运算符
- 逻辑运算符
为元素绑定事件的简易方式
// 想为一个元素绑定事件的流程:
// 1.要让触发事件的那个元素持有一个id
// 2.在js代码中写入如下代码
// 元素id.onclick = function(){
// 当用户点了这个元素之后才执行的代码段
// }
btn.onclick = function(){
// 事件句柄
// 事件句柄(又称事件处理函数),是指事件发生时要进行的操作。每一个事件均对应一个事件句柄,在程序执行时,将相应的函数或语句指定给事件句柄,则在该事件发生时,浏览器便执行指定的函数或语句,从而实现网页内容与用户操作的交互。当浏览器检测到某事件发生时,便查找该事件对应的事件句柄有没有被赋值,如果有,则执行该事件句柄。
console.log(1)
console.log(2)
}
如何简单的获取一个input文本框中填写的内容
1. 让文本框持有一个id
2. `文本框id.value` 的返回值就是input框中目前所输入的内容(String类型);注意时机。
常用的关键字
- var
- function
- typeof
- if
- else
- switch
- for
- while
- break
- new
- case
- finally
- return
- void
- catch
- continue
- this
- witht
- default
- throw
- delete
- in
- try
- do
- instranceof
被保留的关键字
- abstract
- enum
- int
- short
- boolean
- export
- interface
- static
- byte
- extends
- long
- super
- char
- final
- native
- synchronized
- class
- float
- package
- throws
- const
- goto
- private
- transient
- debugger
- implements
- protected
- volatile
- double
- import
- public
数据类型的强制转换
强制转换数据类型的方法
- Number(exp) 将表达式的返回值强制转换为数字类型。
- String(exp) …
- Boolean(exp)
转换规则
-
转Number
- String:纯数字转换结果是字面量的形式转换,其他所有情况均为NaN。
- Boolean: true为1,false为0。
-
转String:所有类型转换为字符串类型就以字面量的形式进行转换。
-
转Boolean
- Number:除了0和NaN以外全部为true。
- String:除了空字符串以外其他情况全为true。
- undefined: undefined是false。
- null:null是false。
==判断相等的总结:
- 数字和Boolean进行比较1true为true,2true为false.
- NaN == NaN 返回false
- undefined == null 返回true
如何判断一个值是否为NaN: isNaN(exp)
如果exp的返回值是NaN则返回true。
==判断具体的流程(了解)
- 有NAN,一律返回false
- 有布尔类型,布尔类型转换成数字比较
- 有string类型,两种情况:
- 对象,对象用toString方法转换成string相比。
- 数字,string类型转换成数字进行比较
- null和undefined不会相互转换,相等
- 有数字类型,和对象相比,对象用valueof转换成原始值进行比较
- 其他情况,一律返回false
语句
条件语句(分支语句,逻辑语句)
if(exp){
语句块
...
....
....
.....
}
// if else语句
if(exp){
分支1
}
else{
分支2
}
switch(变量){
case 常量:{
分支1;
break;
}
case 常量2:{
分支2;
break;
}
case 常量3:{
分支3;
break;
}
default:{
默认分支;
break;
}
}
循环语句
for语句
for(var i = 0;i < 100;i++){
// 循环体
console.log(i)
} 6
while语句
do while语句
while(exp){
//循环体
}
// 至少执行一次版本的while语句
do{
}
while(exp)
break和continue:只能出现在循环语句内部,当循环体内部执行到break关键字时,整个程序会跳出(结束)最近的循环。当循环体内部执行到continue关键字时,程序会结束本一次循环进入到下一次循环。
函数:一段可以被高度复用的代码段。
// 匿名函数:不常见,就是一个没有名字的函数。
function(){
}
// 声明函数
function 函数名(形参1,形参2,形参3...){
//函数体
....
}
// 调用函数
函数名(实参1,实参2,实参3...)
函数的参数
* 形参:在函数体内声明的变量,只声明不赋值。
* 实参:在调用函数时传入的参数,这里相当于是为形参赋值。
! return的作用:只能出现在函数体内部。
1. 控制调用函数表达式的返回值。如果调用的那个函数体内部没有return语句,则一律返回undefined。如果调用的函数体内有return语句,则返回值是return语句后面的表达式的返回值。
2. 做流程控制,如果调用函数时执行到return语句了,那么程序会认为此次执行函数的任务就已经执行完了,就会忽略掉return语句以下的代码。
IIFE自调用函数
var a = (function(n,m){
return (n+m)
})(10,5)
console.log(a)
取三个数的中间值
e=a>b?(a<c?a:(b>c?b:c)):(b<c?b:(a>c?a:c))
||
e=a<b?(a>c?a:(b<c?b:c)):(b>c?b:(a<c?a:c))
!变量作用域
* 全局变量:在全局作用域下声明的变量就是全局变量,这种变量在任何地方都能被访问到.
* 局部变量:在函数体内部声明的变量,这种变量只能在该函数体内部使用,在函数体外无法被访问或操作。
在js中没有块级作用域的概念,只有函数作用域的概念,只有函数才是一个封闭的作用域,在函数体内部声明的变量在函数体外部无法访问。
局部变量和全局变量冲突:以局部变量为准。
如果想在函数体内部声明一个全局变量,那么只要去掉声明变量的var关键字即可。
在局部作用域发生嵌套的时候,内层函数是可以访问到外层函数的局部变量的,反之则不行。
变量提升:JS解释器的一种机制,当我们执行某一个函数的时候,JS解释器会从上到下把函数中的局部变量提取出来放到函数体的顶端先声明但不赋值,此时该变量里面存储的值就为undefined。
参数对象:参数对象的使用场景只是在调用函数时传入实参的数量不确定的情况下,那么我们就会把形参去掉用参数对象arguments
来代替。参数对象的本质是一个类数组,拥有数组下标的特性和.length特性。
数组:若干个值的有序集合。拥有下标的特性,可以使用数组[数字]
的形式从一个数组集合中提取出来某一个元素;拥有.length特性,可以使用数组.length
返回数组中成员的数量(数组的长度)
//!!如何枚举(遍历,循环)一个数组
var 数组;
for(var i = 0; i < 数组.length;i++){
数组[i]
}
数组的全局方法:Array.方法()
- push(exp) 向后插
+ 参数:任意值;任意个
+ 功能:在数组最后添加输入的参数
+ 返回值:返回被增加后的数组的.length
+ 是否改变原数组:会改变原数组
- pop() 删除最后一个
+ 参数:无参数
+ 功能:删除数组的最后一个值
+ 返回值:返回被删除的值
+ 是否改变原数组:会改变原数组
- unshift(exp) 向前插
+ 参数:任意值;任意个
+ 功能:在数组最前添加输入的参数
+ 返回值:返回被增加后的数组的.length
+ 是否改变原数组:会改变原数组
- shift() 删除第一个
+ 参数:无参数
+ 功能:删除数组的第一个值
+ 返回值:返回被删除的值
+ 是否改变原数组:会改变原数组
- splice(exp,exp,exp) 删除,并插入
* + 参数:一个,表示索引
+ 功能:从指定索引,删除到结束
+ 返回值:被删除的值,是一个数组。
+ 是否改变原数组:会改变原数组
* + 参数:两个,第一个表示索引,第二个表示个数
+ 功能:从指定索引,删除指定个数个
+ 返回值:被删除的值,是一个数组。
+ 是否改变原数组:会改变原数组
* + 参数:两个,第一个表示索引,第二个表示个数,从第三个参数开始向后,都是数据
+ 功能:从指定索引,删除指定个数个,并替换成指定数据
+ 返回值:被删除的值,是一个数组。
+ 是否改变原数组:会改变原数组
- slice(exp,exp) 截取数组,并返回新数组
* + 参数:一个,表示索引
+ 功能:从指定索引开始截取,并返回新数组
+ 返回值:新数组。
+ 是否改变原数组:不会改变原数组
* + 参数:两个,第一个表示索引,第二个表示结束索引
+ 功能:从指定索引开始截取,到第二个指定索引之前,并返回新数组
+ 返回值:新数组。
+ 是否改变原数组:不会改变原数组
- reverse() 翻转数组
+ 参数:无参数
+ 功能:翻转数组
+ 返回值:翻转后的数组
+ 是否改变原数组:会改变原数组
- concat() 合并数组,并返回合并之后的数据
+ 参数:任意个,可以是表达式,也可以是另一个数组
+ 功能:合并数组
+ 返回值:新的数组
+ 是否改变原数组:不会改变原数组
- toString() 直把数组转换为字符串,并返回结果。
+ 参数:无参数
+ 功能:转字符串
+ 返回值:字符串
+ 是否改变原数组:不会改变原数组
- join() 使用分隔符,将数组转为字符串并返回
+ 参数:分隔符,任意值
+ 功能:将数组转为字符串,用输入的分隔符隔开
+ 返回值:字符串
+ 是否改变原数组:不会改变原数组
- sort() 按照字符编码的顺序进行排序
+ 参数:无参数
+ 功能:按照字符编码的顺序进行排序
+ 返回值:改变顺序后的数组
+ 是否改变原数组:会改变原数组
sort做数组排序的方法
var a = [1, 4, 51, 51, 61, 32];
a.sort(function(a,b){
return a-b;
})
- indexOf() 查检索成员,找到的话返回下标,否则返回-1
+ 参数:第一个参数:从该数组中
+ 功能:
+ 返回值:
+ 是否改变原数组:
- lastIndexOf() 从后向前搜索字符串
Array.属性
不加括号
Array.方法()
加括号
字符串.length属性和下标的特性
var str ="aabbccddee";
//返回字符串的长度:一共有多少个字符
console.log(str.length)
//字符串的下标特性
console.log(str[2])
//字符串的下标特性只能获取不能修改str[2]="m";
//此操作无效
字符串 str.方法()
- charAt 等同于 str[1]
+ 参数:下标
+ 功能:使用下标查询,并返回相对应的成员
+ 返回值:成员
+ 是否改变原数组:不会
- concat 连接,接收一个或多个字符串,等同于加号
+ 参数:任意个
+ 功能:合并数组
+ 返回值:新的数组
+ 是否改变原数组:不会改变原数组
- indexOf(需要查找的成员,开始索引的位置) 检索成员,找到的话返回下标,否则返回-1
+ 参数:一个字符
+ 功能:检索成员并返回下标,没有的话返回-1
+ 返回值:新的数组
+ 是否改变原数组:不会改变原数组
- lastIndexOf 从后向前搜索字符串
+ 参数:一个字符
+ 功能:检索成员并返回下标,没有的话返回-1
+ 返回值:新的数组
+ 是否改变原数组:不会改变原数组
- replace 替换,将第一个参数替换成第二个参数 惰性匹配
+ 参数:一个字符
+ 功能:检索成员并返回下标,没有的话返回-1
+ 返回值:新的数组
+ 是否改变原数组:不会改变原数组
+ str.replace(/傻子/g,"*");
- slice 截取,
* + 参数:一个,表示索引
+ 功能:从指定索引开始截取,并返回新数组
+ 返回值:新数组。
+ 是否改变原数组:不会改变原数组
* + 参数:两个,第一个表示索引,第二个表示结束索引
+ 功能:从指定索引开始截取,到第二个指定索引之前,并返回新数组
+ 返回值:新数组。
+ 是否改变原数组:不会改变原数组
* 参数为负数时,从后往前数
-
substring 截取,不可为负数,写负数等价于0
-
substr(start,length) 截取,第二个参数为长度
-
split 把传的参数为分割线,分割为字符串数组,不包括传的参数
var str = "asfasraga";
console.log(str);
console.log(str.split("a"))->["", "sf", "sr", "g", ""]
console.log(str);人
JS提供的进制转换方法
- 字符=>ASCII编码
str.charCodeAt - ASCII编码=>字符
string.fromCharCode - 十六进制标号
0x十六进制字符
ES6下的Array的全局方法
- ***forEach()***(function(item, index, array){}) 枚举成员和下标
var arr = [1, 5, 24, 6, 23];
arr.forEach(function(item, index, array) {
// 本次循环出来的成员
console.log(item);
// 本次循环的下标
console.log(index);
// 本循环的数组本身
console.log(array);
})
- map() map可以return,forEach不行
var arr = [1, 5, 24, 6, 23];
arr.map(function(item,index,array){
// 修改原成员
return item+1;
})
+ 参数:item,index,array
+ 功能:可以修改原数组,也可以返回新数组
+ 返回值:新数组
+ 是否改变原数组:不会
- filter() 可以return,并且return必须是true||false
var arr = [1, 5, 24, 6, 23];
arr.filter(function(item,index,array){
return !!(item%2);
})
+ 参数:
+ 功能:
+ 返回值:
+ 是否改变原数组:
- reduce() 累加减乘除
var arr = [1, 5, 24, 6, 23];
arr.reduce(function(temp,temp2){
console.log(temp);
return temp + temp2;
})
+ 参数:两个参数
+ 功能:
+ 返回值:
+ 是否改变原数组:
day6
对象:值得无序集合
- 对象的声明
var wangdawei = {
"name":"王大伟",
"age":18,
"sex":"male",
"students":[
{
"name":"马燕",
"age":16,
"sex":"famale"
}
]
}
console.log(wangdawei)
对象的查询
- Object.属性名
* 把属性名当做常量
* 在Object对象中直接查找某个属性名的所对应的属性值
- Object[“属性名”]
* 把属性名当做常量
* 在Object对象中直接查找某个属性名的所对应的属性值
- Object[属性名]
* 把属性名当做变量
* 需要将该变量赋一个带双引号的属性名,并查询所对应的属性值
对象的修改
- Object.属性名=属性值
- Object[“属性名”]=属性值
对象的删除
- delete Object.属性名
+ 功能:删除对应属性名
+ 返回值:true||false
+ 是否改变原数组:不会改变原数组
对象的检测
- 属性 in Object
+ 功能:检测对应属性是否存在对象中
+ 返回值:true||false
+ 是否改变原数组:不会改变原数组
对象的枚举(也可用作枚举数组)
- for(in)
+ 枚举属性名
for(var i in Object){
console.log(i);
};
+ 枚举属性值
for(var i in Object){
console.log(Object[i]);
};
扩展
- console.log()
+ console是对象
+ log是方法
- document.white()
内置对象,宿主对象
Math对象-方法
- Math.abs(x) 绝对值
- Math.ceil(x) 向上取整
- Math.floor(x) 向下取整
- Math.round(x) 四舍五入
- Math.max(x,y) 取最大值
- Math.min(x,y) 取最小值
- Math.random() 取0-1之间的随机数
* 取0-10之间的整数
parseInt(Math.random()*1)
* 取10-20之间的整数
parseInt(Math.radom()*11)+10
- Math.pow(x,幂) 数值的次方
- Math.sprt(x) 开平方根
- Math.PI() π
Date对象 存储时间
//如果想要使用Date对象,首先需要实例化
// 打开Date对象
var d= new Date();
- d.getFullYear() 返回年份
- d.getMonth() 返回月份(从0开始计数,需要+1)
- d.getDate() 返回日期
- d.getHours() 返回小时数
- d.getMinutes() 返回分钟数
- d.getSeconds() 返回秒数
- d.getDay() 返回星期(周日返回0)
- d.getTime() / Date.parse(日期字符串) 获取时间戳
从1970年1月1日00:00::00到现在一共经过了多少毫秒
后去日期对象(非当前时间)
var target = new Date("2021-02-12 00:00:00");
var now = new Date();
// 距离目标时间总共的秒数
var totalS = Math.floor((target.getTime()-now.getTime())/1000);
// 天
var day = Math.floor(totalS/86400);
// 小时
var hour = Math.floor((totalS%86400)/3600);
// 分钟
var minutes = Math.floor((totalS%3600)/60);
// 秒
var seconds = totalS%60;
console.log(`此时距离过年还有${
day}天零${
hour}小时零${
minutes}分零${
seconds}秒`);
定时器
- setInterval 循环定时器
+ 每隔time的毫秒数后执行一次参数一的函数体
setInterval(fun1,time);
function fun1(){
console.log("执行一次");
};
-
clearInterval 清除定时器
-
setTimeout 延迟定时器
-
clearTimeout 停止延时定时器
-
open(“路径”,“打开页面的名字”,“新打开页面的外观(不能加px)”)
window对象
弹出框:特点阻塞代码执行
- alert(“内容”) 警告框
- prompt([提示信息],[默认值]) 输入框 加中括号意味着可以省略
+ 参数:一个或两个("提示信息","默认值")
+ 功能:输入框
+ 返回值:为字符串
+ 是否有副作用:阻塞代码执行
- confirm([提示信息]) 确认框
+ 参数:一个([提示信息])
+ 功能:确认框
+ 返回值:确定返回true,取消返回false
+ 是否有副作用:阻塞代码执行
location 地址对象
-
location.herf(“http://www.baidu.com”)
-
location.replace(“index.html”)
location.replace(“http://www.baidu.com”)
覆盖原先网页,没有浏览痕迹; -
location.reload(); 刷新
history对象包含用户在浏览器窗口访问过的URL。
- back() 加载history列表中的前一个URL。
- forward() 加载history列表中的下一个URL
- go() 加载history 列表中的某个具体页面,或者要求浏览器移动到制定的页面数量(负数后退,正数前进)
DOM(document object model) 文档对象模型
文档:一个页面就是一个文档,DOM中使用document表示
元素:页面中的所有标签都是元素,DOM中使用element表示
节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示
document内置对象
document对象下的方法
- write() 自带字符串解析
+ 参数:可以是HTML表达式或JavaScript代码。
+ 功能:在页面中打印
+ 返回值:
+ 是否有副作用:***该方法在有事件的情况下会覆盖掉全页面***
- getElementById() 通过(by)id获取(get)元素(element)
+ 参数:Id名是大小写敏感的字符串 (驼峰命名法)
+ 功能:通过id获取元素
+ 返回值:一个Node节点也就是一个元素对象
+ 是否有副作用:无
<div id = "time">2019-12-9</div>
<script>
var timer = document.getElementById("time");
<!-- 打印我们返回的元素对象,更好的查看里面的属性和方法。 -->
console.dir(timer);
</script>
- getElementsByTagName() 通过标签获取元素
+ 参数:标签名
+ 功能:通过标签获取元素(指定标签名的对象集合)
+ 返回值:一个NodeList/节点列表/节点集合
是一个有伪数组下标和Length特性的Object
+ 是否有副作用:无
- getElementsByClassName() 通过class名获取元素
+ 参数:class名
+ 功能:通过class名获取元素
+ 返回值:一个NodeList/节点列表/节点集合
是一个有数组下标和Length特性的Object
+ 是否有副作用:无
- getElementsByName(name属性值)
+ 参数:name属性值
+ 功能:通过name属性值获取元素
+ 返回值:一个NodeList/节点列表/节点集合
是一个有数组下标和Length特性的Object
+ 是否有副作用:无
- querySelectorAll(“css选择器”) 获取节点列表
***querySelector("")***取节点
通过css选择器获取元素
+ 参数:css选择器(子代选择器,群组选择器。。。)(hover不行)
+ 功能:通过css选择器获取元素
+ 返回值:一个NodeList/节点列表/节点集合
是一个有数组下标和Length特性的Object
+ 是否有副作用:无
Node节点:Object数据类型,对应的是页面中的某个元素。
- innerHTML 设置/获取该元素中的内容 ->属性
- className 设置/获取该元素class属性的属性值 ->属性
- setAttribute(“key”,“value”) 设置该元素的某个行内属性的属性值 ->方法
- getAttribute(“key”) 获取该元素的某一个行内属性的属性值 ->方法
- style 设置/获取一个元素的行内样式
Node和NodeList是完全独立的两个存在,方法和属性都不互通
NodeList(节点列表/节点集合)
- 是由若干个Node节点组成的类数组
- 具有数组下标和Length特性
根据层次关系访问节点:(包括文本和元素)
- parentNode 返回节点的父节点
- childNodes 返回子节点集合
- firstChild 返回节点的第一个子节点,最常用的用法是访问该元素的文本节点
* body的第一个儿子是**回撤**
- lastChild 返回节点最后一个子节点
- nextSibling 下一个节点
- previousSibling 上一个节点
根据层次关系访问 元素 节点:
- firstElementChild 返回节点的第一个子节点,最普遍的用法是访问该元素的文本节点
- lastElementChild 返回节点的最后一个子节点
- nextElementSibling 下一个节点
- previousElementSibling 上一个节点
节点的类型
通过nodeType属性来判断节点类型
1代表元素节点
3代表文本节点
节点的增删查改
- 增
* 创建节点 createElement
var oH = document.createElement("h2");
oH.innerHTML = "静夜思";
* 追加/连接 父节点.appendChild(newChild)
newChild 被添加到孩子列表的末端
注:最后要连接body
* 父节点.insertBefore(newChild , referenceNode)
将newChild节点插入到referenceNode之前
- 删除 node.remove()
删除node子节点
<html>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>
<input type="button" value="删除"/>
</body>
</html>
<script>
var oUl = document.querySelector("ul");
var oBtn = document.querySelector("input");
oBtn.onclick = function(){
//删除的元素节点.remove(无参)
//hasChildNodes判断当前的父元素是否还有子节点
if(oUl.hasChildNodes()){
oUl.lastElementChild.remove();
}
}
</script>
-
查
hasChildNodes判断当前的父元素时候还有子节点
返回true||false
注意,标签中的文本内容也算是节点 -
改 node.replaceChild(newChild,oldChild)
用newChild节点替换oldChild节点 -
this:一定出现在函数体内
与事件连用时,代表触发该事件的元素本身
事件
- 事件对象
* 事件: 对某个元素的某种操作
* 事件对象:当某个事件触发时产生的对象,就是事件对象。
event使用前提,必须有事件 不同的对象产生的事件不同。
* 事件对象的兼容: var e = evt || event;
* 事件是由三部分组成:(事件源\事件类型\事件处理程序) 事件类型、事件元素、事件对象
- 鼠标事件对象的属性
- 坐标属性:
- pageX / pageY 相对于整个文档顶部和左侧的坐标 常用
- clientX / clientY 相对于局部窗口的左侧和顶部的坐标
- offsetX /offsetY 相对于内部元素的距离左侧和顶部的坐标 常用于拖拽
-
案例图片跟随(练习)
-
键盘事件对象
- keyUp: 用户释放某一个按键时发生
- keyDown: 用户按下按键时发生
- keyPress: 用户按下按键,并且产生一个字符时发生(意思就是 说按ctrl这样的按键没有效果的)
- keyCode: 获取键盘按键值 字母 对应其ASCII值识别
A:65 a:97 0:48 空格:32 回车:13 Ctrl+ 回车: 10
【注意】:keyPress 的ctrl+回车返回值为10
//转换为字母
console.log(string.fromCharCode(97));
document.onkeypress = function(evt){
var e = evt || event;
if(e.keyCode == 13 || e.keyCode == 10 && e.ctrlKey){
alert("send");
}
}
```
+ ctrlKey:返回当事件被触发时,"Ctrl" 是否被按下,返回值为true or false
**【注意】:键盘检测兼容写方法**
var key = e.keyCode || e.which || e.charCode;
5. 事件流(13)
+ 当某个事件执行时,从子元素向父元素触发 或 从父元素向子元素触发 称为事件流
+ 事件流的两种模式:
- 事件冒泡:从子元素向父元素触发 --->当某个事件触发时,同样的事件会向父元素触发。
但并不是所有事件都会产生冒泡问题 onfocus onblur onload不会产生冒泡问题
- 事件捕获:从父元素向子元素触发
**6.阻止事件冒泡**(13)
+ e.stopPropagation?e.stopPropagation():e.cancelBubble = true; 通过事件对象调用
7. 阻止浏览器默认事件(13)
```js
//阻止鼠标右键冒泡
e.preventDefault?e.preventDefault():e.returnValue = false;
//阻止标签的行为 (跳转)
return false;
- 阻止鼠标右键
//单机右键 控制div的位置
document.oncontextmenu = function(evt){
var e = evt ||event;
oBox.style.left = e.pageX + “px”;
oBox.style.top = e.pageY + “px”;
} - 阻止超链接
- 分享
- details标签+
- contenteditable 内容可编辑
- mark
- data
- datalist
- outerHTML/innerText/innerHTML区别
- innerHTML 将所有的内容都获取出来,包括 HTML 标签,但是不包括自身标签
- innerText 将所有的内容获取出来,不包括 HTML 标签
- outerHTML 将自身以及子元素所有的内容都获取出来 包括 HTML 标签和自身标签
- 自定义属性及getAttribute/setAttribute方法
<div id="d"></div>
//setAttribute("属性名称","属性值名称")
//getAttribute("属性名称") : 返回属性名称对应的属性值
//我们可以通过setAttribute设置自定义属性
var d = document.getElementById("d");
d.setAttribute("heihei",123);
document.write(d.getAttribute("heihei"));
return getComputedStyle(obj,false)[attr]; //针对非ie
- 获取非行内样式(兼容)
- 两个概念:行内样式与非行间样式
- 行内样式:行内样式就是写在标签体内的样式:如, ,在这里color样式就是行内样式。
- 非行内样式:非行内样式就是指不是写在标签体内的style属性的样式。如 内的定义的样式或引用的外部css文件都是非行间样式。
<div id="box" style="color: red;"> </div>
var d = document.getElementById("box");
//获取行内样式
document.write(d.style.color);
#box{
color: blue;
}
var d = document.getElementById("box");
//获取非行内样式
document.write(d.style.color); 返回空
----------------------------------------
#box{
color: red;
font-size: 22px;
}
//照抄 扩展 兼容性
var d = document.getElementById("box");
function getStyle(obj,attr){
//获取非行间样式,obj是对象,attr是值
if(obj.currentStyle){
//针对ie获取非行间样式
return obj.currentStyle[attr];
}else{
return getComputedStyle(obj,false)[attr]; //针对非ie
};
};
document.write(getStyle(d,"color") + "</br>");
document.write(getStyle(d,"font-size"));
-
insertBefore:添加到一个节点前面
父节点.insertBefore(要添加的子节点,参照节点)
参照节点如果为 null 那就和 appendChild() 一样 -
offsetWidth/offsetHeight/offsetLeft/offsetTop
- window.onscroll 事件
111111111111111
…
111111111111111
按钮
-
事件监听 也是时间绑定的一种方法
- 可以为同样的元素绑定多次同一个事件
- 事件元素.addEventListener(“去掉on的事件”,回调函数,是否捕获);
- 可以决定当前的事件流是冒泡还是捕获
- document.addEentListener(“cilck”,function(){
alert(“document”);
},true);
- 可以为同样的元素绑定多次同一个事件
第十三天
-
事件绑定的方式
1.obj.onclick = function(){}
2.
3.addEventListener() 事件监听 -
事件监听 addEventListener() 主流高版本浏览器(13)
事件监听的好处
1—可以为同样的元素绑定多次同一个事件
2—程序员可以使用事件监听的方式 确定触发的过程是冒泡还是捕获事件源.addEventListener(“去掉on的事件”,function(){},true/false) 默认是false 冒泡
// document.addEventListener("click",function(){
// alert("1");
// });
// document.addEventListener("click",function(){
// alert("2");
// });
// document.onclick = function(){
// alert("1");
// }
// document.onclick = function(){
// alert("2");
// }
document.addEventListener("click",function(){
alert("document");
},true);
window.addEventListener("click",function(){
alert("window");
},true);
//一个元素同时拥有捕获和冒泡的情况下,执行顺序是什么?
document.addEventListener("click",function(){
alert("document捕获");
},true);
document.addEventListener("click",function(){
alert("document冒泡");
},false);
window.addEventListener("click",function(){
alert("window捕获");
},true);
window.addEventListener("click",function(){
alert("window冒泡");
},false);
**[注意]先捕获,后冒泡**
- 事件监听兼容(13)
// ie的事件监听 没有第三个参数 默认冒泡
// 该参数不省略on
// document.attachEvent("onclick",function(){
// alert("document");
// });
----------------------------------------------------
//兼容函数 谁 事件 做什么事
function addEvent(obj,type,callBack){
//回调函数
if(obj.addEventListener){
//非IE版本
obj.addEventListener(type,callBack);
}else{
//IE版本
obj.attachEvent("on"+type,callBack);
}
}
addEvent(document,"click",function(){
alert("document")});
-
事件委托(13)
- 委托:让别人去做
- 事件委托:某个事件让其他元素来完成
例如:页面上有1000个li,为每一个li添加单机事件 使用委托只需要在li父级上加一次事件就可以 - 委托的好处:
1. 把某个事件加到父元素上,提高程序的执行效率
2. 动态创建的元素 可以在创建元素的函数体外部为其添加事件 - 委托的机制:
+ 利用事件冒泡(常见) 或者 事件捕获
+ 不是所有事件都可以实现事件委托 常见到也就那么几个
委托的实现方法:
父级元素.事件 = function(){}
<body>
<ul id = "list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
</body>
<script>
//利用事件委托 为每一个li添加单机事件
//处理事件程序为:改变当前操作的li的背景颜色
//委托里不能用this
var oUl = document.getElementById("list");
oUl.onclick = function(evt){
var e = evt || event;
//注意 实际操作的是li
//获取事件源
//targat就代表了当前操作的li
var targat = e.target || e.srcElement;
//alert(targat);
if(targat.tagName == "LI"){
targat.style.backgroundColor = "pink";
}
}
</script>
或
父级元素.(事件,function(){
})
var oUl = document.getElementById("list");
oUl.addEventListener("click",function(evt){
var e = evt || event;
//注意 实际操作的是li
//获取事件源
//targat就代表了当前操作的li
var targat = e.target || e.srcElement;
//alert(targat);
if(targat.tagName == "LI"){
targat.style.backgroundColor = "pink";
}
});
- 事件委托的好处
//为所有的li添加高亮事件
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<ul id = "ulist">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<body>
</body>
</html>
<script>
//为所有的li添加高亮事件
var list = document.getElementsByTagName("li");
for(var i=0; i<list.length; i++){
list[i].onmouseover = function(){
this.style.backgroundColor = "red";
}
list[i].onmouseout = function(){
this.style.backgroundColor = "";
}
}
</script>
//动态添加li元素
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<button id="btn">添加</button>
<ul id = "ulist">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<body>
</body>
</html>
<script>
//为所有的li添加高亮事件
var ulist = document.getElementById("ulist");
var list = document.getElementsByTagName("li");
var btn = document.getElementById("btn");
//创建li
btn.onclick = function(){
var e = document.createElement("li");
e.innerHTML = "新添加的元素";
ulist.appendChild(e);
for(var i=0; i<list.length; i++){
list[i].onmouseover = function(){
this.style.backgroundColor = "red";
}
list[i].onmouseout = function(){
this.style.backgroundColor = "";
}
}
}
</script>
完全版
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<button id="btn">添加</button>
<ul id = "ulist">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<body>
</body>
</html>
<script>
//为所有的li添加高亮事件
var ulist = document.getElementById("ulist");
var list = document.getElementsByTagName("li");
var btn = document.getElementById("btn");
//创建li
btn.onclick = function(){
var e = document.createElement("li");
e.innerHTML = "新添加的元素";
ulist.appendChild(e);
}
// for(var i=0; i<list.length; i++){
// list[i].onmouseover = function(){
// this.style.backgroundColor = "red";
// }
// list[i].onmouseout = function(){
// this.style.backgroundColor = "";
// }
// }
ulist.onmouseover = function(evt){
var e = evt || event;
var target = e.target || e.srcElement;
if(target.tagName == "LI"){
target.style.backgroundColor = "red";
}
}
ulist.onmouseout = function(evt){
var e = evt || event;
var target = e.target || e.srcElement;
if(target.tagName == "LI"){
target.style.backgroundColor = "";
}
}
</script>
- 拖拽效果
拖拽思路: onmousedown onmousemove onmouseup
1.首先为需要拖拽的对象添加一个onmousedown事件
记录:鼠标点击某个对象时的内部偏移量
e.offsetX e.offsetY
2.鼠标在文档上移动
要想让操作的元素动起来,该元素必须有定位
移动的过程,实际上改变,元素的left和top
3.停止移动,需要触发onmouseup鼠标抬起时,取消移动
document.onmousemove = null;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
*{
margin: 0;
}
#box{
height: 100px;
width: 100px;
position: absolute;
cursor: move;
background: url(img/3.jpg);
background-size: 100px 100px;
}
</style>
</head>
<body>
<div id="box">
</div>
</body>
</html>
<script>
var box = document.getElementById("box");
box.onmousedown = function(evt){
//为了获得内部元素距离其左顶点坐标
var e = evt || event;
var ofX = e.offsetX;
var ofY = e.offsetY;
document.onmousemove = function(evt){
var e = evt || event;
box.style.left = e.pageX - ofX + "px";
box.style.top = e.pageY - ofY + "px";
}
document.onmouseup = function(){
document.onmousemove = null;
}
}
</script>
- 拖拽的边界问题
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
*{
margin: 0;
}
#box{
height: 100px;
width: 100px;
position: absolute;
cursor: move;
background: url(img/3.jpg);
background-size: 100px 100px;
}
</style>
</head>
<body>
<div id="box">
</div>
</body>
</html>
<script>
var box = document.getElementById("box");
box.onmousedown = function(evt){
var e = evt || event;
var ofX = e.offsetX;
var ofY = e.offsetY;
document.onmousemove = function(evt){
var e = evt || event;
var x = e.pageX - ofX;
var y = e.pageY - ofY;
if(x<0){
x = 0;
}
var maxLeft = window.innerWidth - box.offsetWidth;
if(x>maxLeft){
x = maxLeft;
}
if(y<0){
y = 0;
}
var maxTop = window. - box.offsetHeight;
if(y>maxTop){
y = maxTop;
}
box.style.left = x + "px";
box.style.top = y + "px";
}
document.onmouseup = function(){
document.onmousemove = null;
}
}
</script>
-
JSON对象(13)
-
json: 轻量级存储工具,是一种跨平台的数据交互格式,
作用:存储数据 -
json对象定义:
var json = {键:值,…};
说明:严格的json对象 键必须用双引号引起来
json的值可以是任意类型的 -
json 操作 赋值和取值
取值: json.键
json[“键”] 用于for in
遍历取值 for in
-
- json应用
console.log(json.name);
console.log(json[“name”]);
- 事件绑定非的三种方式
//1.以js的方法绑定obj.onclick = function(){}
// function f(){
// }
// 等价
// var f = function(){
// }
// f();
//2.以html元素直接绑定
// function fun(){
// console.log("heihei");
// }
//3.事件的监听 也是事件绑定的一种方法
// document.onclick = function(){
// console.log(1);
// }
// document.onclick = function(){
// console.log(2);
// }
第十三天笔记
- 正则表达式
- 拖拽效果的思路: onmousedown onmousemove onmouseup
- 首先为需要拖拽的对象添加一个onmousedown事件
记录:鼠标点击某个对象时的内部偏移量
e.offsetX e.offsetY
- 鼠标在文档上移动
要想让操作的元素动起来,该元素必须有定位
移动的过程,实际上改变,元素的left和top
- 停止移动,需要触发onmouseup鼠标抬起时,取消移动
document.onmousemove = null;
- 拖拽的边界问题
<script>
var box = document.getElementById("box");
box.onmousedown = function(evt){
var e = evt || event;
var ofX = e.offsetX;
var ofY = e.offsetY;
document.onmousemove = function(evt){
var e = evt || event;
var x = e.pageX - ofX;
var y = e.pageY - ofY;
if(x<0){
x = 0;
}
var maxLeft = window.innerWidth - box.offsetWidth;
if(x>maxLeft){
x = maxLeft;
}
if(y<0){
y = 0;
}
var maxTop = window.innerHeight - box.offsetHeight;
if(y>maxTop){
y = maxTop;
}
box.style.left = x + "px";
box.style.top = y + "px";
}
document.onmouseup = function(){
document.onmousemove = null;
}
}
</script>
- 正则:正确的规则
什么是正则表达式
-
正则表达式(regular expression)是一个描述字符规则的对象。如:只能出现字母,只能出现数字,前三个必须是数字等。
为什么要使用正则表达式
-
前端往往有大量的表单数据校验的工作,采用正则表达式会使得数据校验的工作量大大减轻,如邮箱验证,手机号码,等等。比起用字符串的函数来判断简单,易用。
-
正则表达式的组成:普通字符 或者 特殊字符
-
定义:
- 字面量
var reg = /普通字符或者特殊字符/修饰符 - 构造方法
var reg = new RegExp(“a”,“i”);
console.log(reg.test(“a”));
var reg = new RegExp("\d");
console.log(reg.test(“1”));
- 字面量
- 正则中的特殊字符:
-
单个字符:
^:正则开始
$ : 正则结束
. : 元字符, 表示任意一个字符
. : 表示转义字符 .表示.
+ :表示其前面紧挨着的字符至少出现1次 等价{1,}
* :表示其前面出现的字符至少出现过0次 等价{0,}
? :表示其前面出现的字符至少出现过0次,至多1次 等价{0,1}
| : 表示或者 -
组合字符:
\d : 0-9之间的任意一个数字 \d只占一个位置
\D : 除了\d
\w : 数字,字母 ,下划线 0-9 a-z A-Z _
\W : 除了\w
\s : 空格或者空白等
\S : 除了\s -
括号:
{m,n}表示括号前面紧挨着的字符至少出现m个,至多出现n个 : 以b 开头 至少3个a 至多5个a /^ba{3,5}&/
{m}表示括号前面紧挨着的字符只能出现m个
{m,}表示括号前面紧挨着的字符至少出现m个
[] 表示括号内的任意一个字符
[wd3h]
[a-z]表示任意一个小写字母 [a-zA-Z0-9]
[^ ]表示非括号内的任意一个字符
()一般与或连用 表示优先级
[\u4e00-\u9fa5] 任意一个中文字符
-
-
密码强弱判断
一类字符 是 弱 纯数字 弱 纯字母 弱 纯 特殊字符 弱
两类字符 是 中
三类字符 强 包含数字 字母 特殊字符 -
表单验证
action提交的位置 method提交的方式
-
表单验证强化版:焦点验证
通常一个表单内容特别多,如果每次全部填写完成才能表单提交,这样对用户的体验非常不好。
userPwd.onblur = function(){ //焦点验证方式 -
正则中的相关方法及属性
正则中的相关方法:
+ test() 检验一个字符串是否符合某一个正则规范,如果符合返回true,否则返回false
用法: reg.test(str)
+ exec 根据正则表达式查找,结果满足,会返回一个长度为1的数组(数组只有一个值)
用法:reg.exec(str)
+ lastIndex :这个属性记录的就是下一次捕获从哪个索引开始。
var reg = /\d/g;
var str = "92a345a678a9";
console.log(reg.exec(str));
console.log(reg.lastIndex);
g---------------全局
i---------------忽略字母大小写
n---------------多行匹配
<---------------------------------------------------------------------------------------------->
+ 正则中相关字符串的方法:
- search方法 返回与正则表达式查找内容匹配的第一个子字符串的位置
用法:str.search(reg)
说明:如果找到则返回子字符至开始处的偏移位,否则返回-1。
<!-- var r, re; // 声明变量。
var s = "The rain in Spain falls mainly in the plain.";
re = /falls/i; // 创建正则表达式模式。
re2 = /tom/i;
r = s.search(re); // 查找字符串。
r2 = s.search(re2);
document.write("r:" + r + ";r2:" + r2);// 返回 Boolean 结果。 -->
- match 方法
使用正则表达式模式对字符串执行查找,并将包含查找的结果作为数组返回。
str.match(rgExp)
var reg = /\d+/g;
var str = "123a4356a987";
console.log(str.match(reg));
- replace 方法
返回根据正则表达式进行文字替换后的字符串的复制。
stringObj.replace(rgExp, replaceText)
var reg = /laowang/g;
var str = "laowang的隔壁也住着laowang";
console.log(str.replace(reg,"dahuang"));
ES6
- let语法
let是什么?
let用来声明变量,它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效,类似于C,C++,JAVA局部变量的概念。
基本用法:
+ 块及作用域
{
var a = 10;
let b = 123;
}
console.log(a);
console.log(b);
上面代码在代码块之中,分别用let和var声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量无法被打印,var声明的变量返回了正确的值。
这表明,let声明的变量只在它所在的代码块有效。
for(let i=0; i<10; i++){
document.write(i);
}
document.write(i);//x 看不到
上面代码中,计数器i只在for循环体内有效,在循环体外引用就会报错。
+ 暂时性死区
下面代码在有两个同名变量a,但是却由于{
}使得作用域不同,输出结果为123,456。在被let修饰的同名变量下,根据就近原则,内部变量屏蔽外部变量。
let a = 456;
{
let a = 123;
console.log(a);
}
console.log(a);
+ 不存在变量提升
var命令会发生”变量提升“现象,即变量可以在声明之前使用,值为undefined。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
也就意味着被let声明的变量,必须先定义在使用。
+ 不允许重复声明
var a = 123;
var a = 123; // 可以实现
let b = 123;
let b = 123; // Identifier 'a' has already been declared
* this与bind
+ this:a.当this出现在普通方法时,this代表调用当前方法的对象本身。
b.当this出现在事件中时,this代表调用当前事件的HTML元素本身。
常规函数
function fun(){
console.log(this);
}
fun();
匿名函数
setTimeout(function(){
console.log(this);
},2000);
事件
document.onclick = function(){
console.log(this);
}
+ bind(this重新指代的对象): 只能为匿名函数服务
<head>
<style>
#box{
width: 100px;
height: 100px;
background: #FF0000;
}
</style>
</head>
<body>
<div id="box">
</div>
</body>
var box = document.getElementById("box");
document.onclick = function(){
this.style.display = "none";
}.bind(box);
+ 有名函数重新指定this对象: apply call
function fun(){
console.log(this);
};
// fun.apply(box);
// fun.call(box);
fun();
*3. JSON.parse/JSON.stringify* 正反解析
JSON字符串和对象直接的转换:
var str = '{"id":"123","name":"大黄"}';
var obj = JSON.parse(str);
document.write(obj.id + " " + obj.name);
var obj1 = {
"id":"123","name":"大黄"};
var str1 = JSON.stringify(obj1);
document.write(str);
4. const用法
什么使const命令呢?实际上它也是一种声明常量的方式。
const命令用来声明常量,一旦声明,其值就不能改变。也就是只读变量。
const a=10;
a=100; // Assignment to constant variable. 报错
基本用法:
+ 声明常量
const PI = 3.1415;
PI // 3.1415
PI = 3;
// TypeError: Assignment to constant variable.
+ 常量必须初始化
const foo;//报错 Missing initializer in const declaration
+ 块级作用域
{
const foo = 123;
}
console.log(foo);
上述代码依然报错,和let的效果是一样的。
+ 声明不提升(const修饰的变量必须先定义后使用)
if (true) {
console.log(MAX); // ReferenceError
const MAX = 5;
}
+ const修饰的变量不可重复定义
简单来说,let和const的功能基本类似,只是let用来修饰变量,const用来修饰常量。
无论是let还是const,这并不算新的语法,其实这些内容甚至是其他高级语言"玩剩下的",这种改动只是将JS脚本语言更加标准化了,
可见js的语法也更加的后台化。
5. for..in...和for...of...
let strArr = ["heihei","haha","laowang"];
for(let index in strArr){
//遍历下标
console.log(strArr[index]);
}
for(let t of strArr){
//遍历值
console.log(t);
轮播图
运动原理
- 用计时器不停的去获取一个元素的某一个行内样式的属性值并进行一个计算然后把计算结果重新赋值给这个元素。
移动的套路
- 被移动的元素要有初始的行内样式
- 在计时器里要不停的获取到这个行内样式的值并用parseInt()或parseFloat()的方法强制转换为数字
- 要将得到的数字进行一定的计算后重新赋值给这个元素(注意单位)
- 间隔时间的取值范围要在16ms~32ms之间 (追求丝滑 追求性能)
- 判断结束情况,在满足结束情况下要清除掉计时器.
5.1) 一般不要判断相等
5.2) 在结束动画的判断语句里,要把元素的样式写成最终形态,防止冲过。
this关键字出现的场景与指向问题
- 对象是属性和方法的集合------this出现的场景
- 面向对象语言中 this 表示当前对象的一个引用。
- 出现在一般函数内或全局作用域下,指向的window对象
- 出现在事件处理函数时,指向触发事件的元素(Node节点)
- 出现在对象的方法中:指向的该对象
- 出现在构造函数中:指向的是实例化对象
- 出现在原型对象的方法中:指向的是调用该方法的对象。
购物车
- 绑定nodeList事件节点
function bindEvent(nodeList,eventType,fn){
for(let i = 0; i < nodeList.length; i++){
nodeList[i][eventType] = fn;
}
}
AJAX(http脚本化) 使用javascript来操作HTTP请求
服务器 server
客户端 client
端口号: 每个电脑都有65535端口
IP地址
HTTP请求 (异步请求)
DNS: 将域名转换为IP地址的过程
域名 domain name
dir目录 Ipconfig:IP地址
response 响应 stauts code 状态码
1. onreadyStatechange:存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。
2. readyState :存有 XMLHttpRequest 的状态。从0到4发生变化。
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪
3. 200: "OK" 404: 未找到页面
btn.onclick =function(){
//1.实例化XMLHttpRequest对象
let http = new XMLHttpRequest()
//2.规划一个HTTP请求
//(2.1)methods: String,请求方式,可以是'get' 也可以是'post'
//(2.2)url: String,请求地址,比如:"http://192.168.0.1/xxxx.txt"
//(2.3)async :Boolean,同步或异步,可选参数,默认的异步的
//http.open(method,url,async)0000000
http.open('get',"http://192.168.0.1/xxxx.txt",false); //false同步请求
//3. 发送HTTP请求
http.send();
//4. 接收来自服务器端的请求
// console.log(http.responseText);
/* Java中的同步交互:指发送一个请求,需要等待返回,然后才能够发送下一个请求,有个等待过程;
异步交互:指发送一个请求,不需要等待返回,随时可以再发送下一个请求,即不需要等待。
区别:一个需要等待,一个不需要等待,在部分情况下,我们的项目开发中都会优先选择不需要等待的异步交互方式。 */
http.onreadystatechange = function(){
//服务器端已将返回的内容交付给客户端手里了
if(http.readyState === 4){
console.log(http.responseText);
}
}
}
带请求参数的
http.open(“get”,“http://10.35.164.167/data.php?name=墨轩&age=21”);
思路: 回车 onclick事件 发送参数 生成节点 返回内容正解析 生成节点 加载动画
<----------------------------------------------------------------------------------------------------------------------------------->
ajax(HTTP脚本化):使用JavaScript来操作HTTP请求。
// 1. 实例化XMLHttpRequest对象
let http = new XMLHttpRequest()
// 2. 规划一个HTTP请求
// methods: String,请求方式,可以是"get"也可以是"post"
// url:String,请求地址,比如:"http://192.168.0.1/xxxx.txt"
// async:Boolean,同步或异步,可选参数,默认是异步的。
http.open(method,url,async)
// 3. 发送HTTP请求
http.send()
// 4. 接收来自服务器端的请求
http.onreadystatechange = function(){
if(http.readyState === 4){
console.log(http.responseText)
}
}
*//封装一个参数,对象
function ajax(opt) {
if (!opt.method) {
//没传给默认值
opt.method = "get"; //false
}
// 1.实例化XMLHttpRequest对象
let http = new XMLHttpRequest();
// 2.规划一个HTTP请求
http.open(opt.method, opt.url);
// 3.发送HTTP请求
http.send();
// 4.接收来自服务器端的请求
http.onreadystatechange = function() {
if (http.readyState === 4) {
opt.success(http.responseText);
}
}
}
*//封装三个参数
在请求时,发送请求参数。
// 规划了一个无请求参数的请求
http.open("get","http://10.35.164.50/message.php");
http.open("get","http://10.35.164.50/message.php?name=wangdawei&age=18&sex=1");
webServer:将本机的某一个端口(一般来说是80或443)对外开放,允许其他电脑向你的这个端口发送请求,你还会给别人返回一个文件。
* NG
* IIS
* Apache
集成环境
* PHP
* Apache
* MYSQL
JSON的正反解析
JSON.stringify(xxxx)
反解析JSON.parse(xxxx)
正解析
数据库:MySQL、PostgresSql、Oracle、SQLite、SQLServer、MariaDB、Amazon AWS、Oracle Cloud、阿里云、腾讯云、Microsoft Azure
MySql
SQL DML 和 DDL
可以把 SQL 分为两个部分:数据操作语言 (DML) 和 数据定义语言 (DDL)。
SQL (结构化查询语言)是用于执行查询的语法。但是 SQL 语言也包含用于更新、插入和删除记录的语法。
查询和更新指令构成了 SQL 的 DML 部分:
SELECT - 从数据库表中获取数据
UPDATE - 更新数据库表中的数据
DELETE - 从数据库表中删除数据
INSERT INTO - 向数据库表中插入数据
SQL 的数据定义语言 (DDL) 部分使我们有能力创建或删除表格。我们也可以定义索引(键),规定表之间的链接,以及施加表间的约束。
SQL 中最重要的 DDL 语句:
CREATE DATABASE - 创建新数据库
ALTER DATABASE - 修改数据库
CREATE TABLE - 创建新表
ALTER TABLE - 变更(改变)数据库表
DROP TABLE - 删除表
CREATE INDEX - 创建索引(搜索键)
DROP INDEX - 删除索引
逗号分隔修改对多个字段
数据库的结构关系:库(文件夹) > 表 > 列(字段) > 行(数据)
数据类型
int 整型(整数数字) float 浮点型(小数) varchar 字符型(字符串)
date 日期(YYYY-MM-DD) datetime 日期时间 (YYYY-MM-DD HH-MM-SS)
<!-- 查数据表内所有数据-->
SELECT * FROM 表名
<!--查根据条件查询数据
SELECT * FROM 表名 WHERE 字段名 = 某值
SELECT * FROM
表名 WHERE 字段名 = 某值 AND 字段名 = 某值
SELECT * FROM
表名 WHERE 字段名 =某值 OR 字段名 = 某值
<!--根据某个字段名进行排序-->
SELECT * FROM 表名 ORDER BY 字段名
<!--根据某个字段名进行反向排序 SELECT * FROM 表名 ORDER BY 字段名 DESC
<!--删除表内所有数据-->
DELETE FROM 表名
1 -- SELECT name,id FROM students WHERE sex=0 OR city="辽宁
3 -- DELETE FROM students
5 -- DELETE FROM students WHERE city= "gansu"
UPDATE Person SET Address = 'Zhongshan 23', City = 'Nanjing'
WHERE LastName = 'Wilson'
<!-- 查根据条件删除数据-->
DELETE FROM 表名 WHERE 字段名 = 某值
<!-- 插入新数据-->
INSERT INTO 表名(字段名1,字段名2, 字段名3,....) VALUES (值1, 值2,值3,.....)
<!--根据条件修改数据-->
UPDATE 表名 SET 字段名 = 某值,字段名 = 某值.... WHERE 字段名 = 某值
PHP ASP.NET JAVA C C++ PYTHON Nodejs...
ctrl + c 按两次退出node.js运行环境
Nodejs
模块:用require()引入的一个对象;一类是系统模块,还有一类是第三方模块。
fs模块 (fileSystem
// 异步写入
fs.writeFile("路径","写入的数据",function(){
})
// 异步读取
fs.readFile("test.txt",function(error,data){
if(error){
console.log("读取失败")
return;
}
console.log(String(data))
})
[举例]
//写入文件
// for(let i = 1; i <= 100;i++){
// fs .writeFileSync( data/hello$ . txt i,String(Math. random( )))
// console.log( 第${i}次写入数据完成” )
// }
// 读取文件
fs.readFile("test. txt", function(error, data) {
if (error) {
console.log("读取失败")
return;
}
console.log(String(data))
})
//异步读取
fs.readyFile("test.txt",function(error,data){
if(error){
console.log("读取失败");
return;
}
console.log(String(data));
})
监听来自前端的http请求
MySQL-npm 查询 cls清屏 ctrl + c 停止服务
history.go(1); location.reload(); 自动加载
将npm下载地址切换为国内淘宝镜像:npm config set registry http://registry.npm.taobao.org
下载安装第三方模块:npm install 模块名 --save
第三方模块官网集合:https://www.npmjs.com/
##### express(第三方模块) 作用:开放本机的一个端口,对外提供一个网站服务
//让nodejs处理来自前端的路由请求,apache处理静态页面请求
let server = require("express")();
let fs = require("fs");
// 计划监听来自前端的HTTP请求,如果请求地址是/a则自动调用第二个参数的函数体
server.get("/a",function(request,response){
// 接收到来自前端的请求name参数,并赋值到name变量中
let name = request.query.name;
console.log("接收到来自前端的请求")
// 向前端返回一段内容
response.send(`${
name},success!!!!`)
})
// 真正将上面的计划执行监听到本机的81端口上。
server.listen(81)
##### mysql(第三方模块)
let mysql = require('mysql');
// 规划链接
let sql = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '123456',
database : 'tech'
});
// 尝试链接
sql.connect();
// 执行sql任务 //data返回的json对象数据
sql.query("SELECT * FROM students",function(error,data){
if(error){
console.log(error)
}
else{
console.log(data) //返回的是二进制,json,字符串
}
})
*#### 解决跨域问题的代码 (服务器反向代理,后端独立处理,前端看不见)*
server.all("*",function(req,res,next){
//设置允许跨域的域名,*代表允许任意域名跨域
res.header("Access-Control-Allow-Origin","*");
//允许的header类型
res.header("Access-Control-Allow-Headers","content-type");
//跨域允许的请求方式
res.header("Access-Control-Allow-Methods","DELETE,PUT,POST,GET,OPTIONS");
if (req.method.toLowerCase() == 'options')
res.send(200); //让options尝试请求快速结束
else
next();
})
浏览器的同源组策略:就是浏览器保护浏览器安全的一种机制,它不允许客户端请求从A服务器请求过来的页面往B服务器去发送Ajax请求。
同源组策略如何判断两个服务器是否是同一台服务器:同协议,同主机(域名或IP地址),同端口才为同域。其中有任何一项不一致都认为是不同域,即发送AJAX请求会被阻止并报跨域错误。
### JSONP:非标准技术,是一种解决跨域限制问题的一种方式。
JSONP的工作机制:前端使用一个script标签来创建一个HTTP请求,并且事先声明一个回调函数,该回调函数的名字由callback参数的参数值发送给后端。后端接收到来自前端的请求后利用callback参数的参数值和要给前端返回的数据拼接成一段JS执行函数的代码段,此时实参就是要返回给前端的数据。前端接收到后端返回的结果后,会自动的执行事先声明好的回调函数,此时函数的形参就代表了后端要返回的数据(实参)。
- JSONP的优缺点
- 1.优点
1.1它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制,JSONP可以跨越同源策略;
1.2它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持
1.3在请求完毕后可以通过调用callback的方式回传结果。将回调方法的权限给了调用方。这个就相当于将controller层和view层终于分 开了。我提供的jsonp服务只提供纯服务的数据,至于提供服务以 后的页面渲染和后续view操作都由调用者来自己定义就好了。如果有两个页面需要渲染同一份数据,你们只需要有不同的渲染逻辑就可以了,逻辑都可以使用同 一个jsonp服务。 - 2.缺点
2.1它只支持GET请求而不支持POST等其它类型的HTTP请求
2.2它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
2.3 jsonp在调用失败的时候不会返回各种HTTP状态码。
2.4缺点是安全性。万一假如提供jsonp的服务存在页面注入漏洞,即它返回的javascript的内容被人控制的。那么结果是什么?所有调用这个 jsonp的网站都会存在漏洞。于是无法把危险控制在一个域名下…所以在使用jsonp的时候必须要保证使用的jsonp服务必须是安全可信的
- 1.优点
请求第三方的商业接口
下载Node全家桶:$ npm install mysql express express—static ejs --save
已经做好的项目如何上线
nodejs apache-20 phpnow express 申请域名,远程服务器
数据通信和模板引擎 ejs vue、框架
将div = 变 - ,正常出现
ejs.renderFile("details.html",{
info:data[0]}, function(error,result){
if(error){
console.log(error)
return;
}
response.end(result)
});
<ul>
<% studentsList.forEach(function(item){
%>
<li>
<a href="/info?id=<%= item.id %>">
姓名:<%= item.name %>
年龄:<%= item.age %>
性别:<%= item.sex ? "男" : "女" %>
籍贯:<%= item.city %>
</a>
<p>
<%- item.info %>
</p>
</li>
<% }) %>
</ul>
前后端的开发模式 重前端和重后端
10M带宽 (木桶效应)
下行带宽 10M/8 ≈ 1.25M/S 下行峰值 125KB/S
上行带宽 10M/16 ≈ 625KB/S (对于服务器重要) 62.5KB/S
计算机中以二进制进行运算.
2的十次方为1024,有时为了方便就约为1000.
存储之间的关系为B(字节),KB(千字节),MB(兆字节),GB(吉字节)
它们之间的关系为2的十次方倍.
1KB=1024B
1MB=1024KB
1GB=1024MB
因此,10M=10240KB
expresse-static:NodeJS环境中向前端提供静态服务的第三方模块,可以代替Apache。
const server = require("express")();
const expressStatic = require("express-static")
const mysql = require('mysql');
const port = 8080;
// 拦截所有请求,并且声明静态请求目录
server.use(expressStatic(`${
__dirname}/static`));
#### jQuery
原生JS和jQuery转化 加$或加下标
* $方法的四种传参形式
$("css选择器") // 返回与css选择器相匹配的jQuery对象
$(Node) // 返回与Node节点相匹配的jQuery(将Node节点转换为jQuery对象)
$("HTML代码段") // 根据HTML代码段生成一个或若干个jQuery对象的
$(function(){
}) // 类似于window.onload事件,完全等价于document.onready
+
### * jQuery对象:一个由若干个Node节点构成的类数组(arguments);不同于Node和NodeList,Node节点和jQuery对象下的方法与属性互相独立。
jQuery对象下的方法:
* addClass() //为jQuery对象所有的元素追加类名
* removeClass() //移除类名
* hasClass() //检测元素是否含有某个类型,返回Boolean
* toggleClass() //追加/删除类名
* html() //设置/获取开始标签与结束标签之间的内容
* val() //设置/获取元素的value属性的属性值
* attr(key,value) //设置/获取元素的自定义属性的属性值
* closest("css选择器") //从调用方法的jQuery对象开始,逐层向上寻找与css选择器相匹配的父级元素,直到找到一个匹配到的元素就停止寻找并将其返回。
* find("css选择器") //在调用方法的jQuery的内容寻找与css选择器相匹配的所有的后代元素
* parents() //返回祖先级dren() //返回所有子孙级们们
* chil
* animate(css对象,speed,callback) //操作/获取一个元素的行内样式 带动画的
* next() //下一个兄弟节点
* prev() //上一个兄弟节点
* nextAll() //下面的所有的兄弟节点
* prevAll() //上面的所有的兄弟节点
* remove() //删除元素
* clone(true) //克隆元素,参数代表是否连同事件一块儿克隆。
* append(jquery对象) //插入到元素的结束标签的前面 等价于原生js中appendChild
* appendTo() //对标的是appendChild,将调用方法的对象和参数对象做了调转。
* prepend() //插入到元素的开始标签的后面
* prependTo()
* after() //插入到元素的后面当做下一个兄弟节点
* before() //插入到元素的前面当做上一个兄弟节点
* show()
* hide()
* toggle() //显示时隐藏 隐藏时显示
* fadeIn(time,callback) //淡入
* fadeOut(time,callback)
* fadeToogle(time,callback)
* slideDown(time,callback)
* slideUp(time,callback) //向上滑动
* slideToggle(time,callback)
* each(function(){
}) //枚举jQuery对象结果集每一个元素
* eq(index) //从jQuery结果集中根据下标提取出某一个元素
* index() //返回该元素在其父级元素中与其他兄弟节点的相对下标
* css() //操作/获取一个元素的行内样式
绑定事件
jQuery对象.去on的事件名(function(){
// 事件处理函数
// this 原生JS对象
this
})
// 为jQuery对象设置若干个行内样式
jQuery.css({
css属性名:css属性值,
//fontSize:12,
css属性名:css属性值
// height:300
})
// 获取jQuery对象的行内属性的属性值
```
```js
$(".div1").animate({
marginLeft:300,
width:500,
height:500
},3000,function(){
$(".div1").animate({
marginTop:300,
width:300,
height:300,
},3000)
})
jQuery发送ajax请求或jsonp请求
// 发送一个ajax 请求
$.ajax({
// 请求地址
url:"http://127.0.0.1/steamDataAPI.php",
// 请求参数
data:{
name:"王大伟",
age:18
},
// 同步/异步(true 默认)
async:false,
// 请求方式: 默认值是GET
method:"get",
// 回调函数:当客户端接收到服务器端返回的内容时,触发的回调函数
success(data){
console.log(JSON.parse(data))
}
})
// 发送一个JSONP 请求
$.ajax({
// 请求地址
url:"http://10.35.170.93/steamjsonp.php",
// 该请求不是标准的Ajax请求,请求底层原理使用jsonp的方法向后端发送请求
dataType:"jsonp",
// 回调函数:当客户端接收到服务器端返回的内容时,触发的回调函数
success(data){
console.log(data)
}
})
### jQuery ajax
$.ajax({
url:"http://10.35.164.50:8080/test",
data:{
id:1,
name:"wangdawei"
},
dataType:"jsonp",
method:"GET",
async:false,
// HTTP请求成功之后触发的回调
// 也就是HTTP状态码是2开头或3开头的是成功请求
success:function(data){
console.log(data)
},
// HTTP请求成功失败触发的回调
// 也就是HTTP状态码是4开头或5开头的是失败请求
// error:function(){
// },
// HTTP请求结果接收到之后触发的回调
// complete:function(a,b){
// console.log(a.responseText)
// },
beforeSend:function(){
console.log("正准备发送请求")
},
//修改jsonp请求中带有函数名参数的名字(一般默认是callback)
jsonp:"cb"
// 修改回调函数的函数名
jsonpCallback:"wangdawei"
})
构造函数:如果函数中的逻辑是生成一个对象的并将其返回(生产对象的函数。)
function Person(name,age,sex){
// 需要传递参数的值是可变的属性
// 私有属性
this.name = name;
this.age = age;
this.sex = sex;
}
// 构造函数的原型对象
// 原型属性和原型方法
Person.prototype.type = "灵长类";
Person.prototype.sayName = function(){
alert(this.name)
}
// 实例化
let wdw = new Person("王大伟",18,"男");
let hhl = new Person("何恒磊",17,"男");
let sy = new Person("石钰",16,"女");
* 实例化对象.__proto__ 返回该实例化对象的构造函数的原型对象
* 实例化对象.constructor 返回该实例化对象的构造函数的引用 (产品到工厂)
* 构造函数.prototype 返回该构造函数的原型对象
原型prototype的使用场景:
-
用途
- 把构造函数的公共的属性和方法从私有属性中提取到原型对象中,以达到节省内存的目的.
- 本地对象的扩展.
-
原型的理解:
每一个构造函数都有一个prototype属性,该属性指向了一个对象,这个对象我们叫原型对象。通过构造函数生成的实例化对象,如果在调用属性或方法时从自身找不到该属性或方法,此时不会直接报错或返回undefined,而是去找它的构造函数的原型对象,看它里面有没有该属性或方法,如果有则直接借用,如果没有则看看该原型对象还有没有prototype属性,如果有则重复上面的操作,如果没有则返回undefined或报错。
//为字符串对象扩展了全局(原型)方法
String.prototype.reverse = function(){
var result = ""
for(var i = 0; i < this.length;i++){
result += this[this.length - 1 - i]
}
return result;
}
js的继承
// es5继承
function Person(name,sex,age){
this.name = name;
this.age = age;
this.sex = sex;
}
Person.prototype.type = "灵长类";
function SuperMan(name,sex,age,skill){
// 继承来自父类Person的所有私有属性
Person.apply(this,[name,sex,age]);
this.skill = skill;
}
// 继承来自父类Person的所有的原型属性和原型方法
SuperMan.prototype = new Person();
SuperMan.prototype.fadazhao = function(){
alert(this.skill)
}
let spiderMan = new SuperMan("蜘蛛侠","男",18,"吐丝儿")
- call和apply区别:
call和apply都是函数的方法,该方法可以帮助函数调用一次自己,但是和普通调用不同,call和apply的调用可以调整本次执行函数中this的指向,这个指向会被第一个参数代替。
如果这个函数在调用数需要传递实参,那么call方法会把实参依次排列在第一的参数之后,而apply则是将实参放到一个数组中,并把数组作为apply方法的第二个参数。call和apply常常被用在构造函数实现继承功能的场景下。
function fn(num1,num2){
console.log(this)
console.log(num1 + num2)
}
// 以下的两种写法是完全等价的。
fn()
fn.call()
// 调用并改变本次函数的this指向
fn.call(1)
// 调用并改变本次函数的this指向并传入实参
fn.call("hello",1,2)
// 调用并改变本次函数的this指向
fn.apply(1)
// 调用并改变本次函数的this指向并传入实参
fn.apply("hello",[1,2])
ES6的类和继承
class Person {
constructor(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
sayName(){
alert(this.name)
}
}
let wdw = new Person("王大伟",18,'男')
class SuperMan extends Person{
constructor(name,age,sex,skill){
// 继承父类的私有属性
super(name,age,sex)
this.skill = skill
}
dazhao(){
alert(this.skill)
}
}
let gangtiexia = new SuperMan("钢铁侠",18,"男","钞能力");
class Person {
constructor(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
sayName(){
alert(this.name)
}
}
let wdw = new Person("王大伟",18,'男')
class SuperMan extends Person{
constructor(name,age,sex,skill){
// 继承父类的私有属性
super(name,age,sex)
this.skill = skill
}
dazhao(){
alert(this.skill)
}
}
let gangtiexia = new SuperMan("钢铁侠",18,"男","钞能力");
JS如何实现继承
- 使用对象冒充:
在这里插入图片描述—
- 理解:
在本构造函数中将其他构造函数视为本类的一个属性,并执行,从而实现了对超类的拷贝 - 优点:
简单直接,思路清晰,可以实现多重继承,体现了类似Java等语言面向对象的原理 - 缺点:
由于将其他构造函数的属性和方法嵌套到本类来,难免会发生属性和方法冲突,由于程序是自上到下运行的,先定义的同名的属性和方法会被覆盖掉。
- 使用es6 class关键字实现
在这里插入图片描述—
- 理解:
使用class / expends / super 关键字模拟Java等语言面向对象的原理,实现继承,本质上是对原型继承的封装与改写,形式更加纯正。 - 优点:
形式体现了面向对象的风格,易于理解 - 缺点:
只能在es6中使用,配合js其他语法(如对象扩展符,原型方法等)容易产生混淆和误解
- 构造函数绑定
在这里插入图片描述—
- 理解:
改变超类的执行环境,在基类实例的运行环境中运行,使得基类实例拥有超类构造函数的所有方法和属性。 - 优点:
代码简洁,可以在call或apply方法中传参,获取超类非预定义属性(有传入变量决定属性) - 缺点:
基类无法继承超类原型上的方法,属性和方法继承会出现覆盖问题。
- 原型继承
在这里插入图片描述—
- 理解:
改变基类的原型,指向超类的实例,进而实现继承。 - 优点:
各类js继承的核心和晕头,是js语言的灵魂之处;基类可以获得超类原型上的属性和方法;可以向超类原型中传参。 - 缺点:
理解难度高;无法实现多重继承(基类prototype只能绑定为一个超类的实例);注意属性和方法的覆盖问题;原型继承将会因为原型链上溯(还有一个类继承了基类)而出现混淆问题。
cookie
// 设置一个会话cookie
// document.cookie = "age=18";
// 设置存储日期
// let date = new Date("2020-12-05 01:00:00");
// document.cookie = `name=wangdawei;expires=${date}`;
// 读cookie
function getCookie(key){
let cookie = document.cookie;
let arr = cookie.split("; ");
let result = {
}
arr.forEach(item=>{
let key = item.split("=")[0];
let value = item.split("=")[1];
result[key] = value;
})
if(key){
return result[key];
}
return result;
}
// 删cookie
function removeCookie(key){
let guoqu = new Date("1970-01-01 00:00:00")
if(key){
document.cookie = `${
key}=beybey;expires=${
guoqu}`
}
else{
let cookie = getCookie();
for(let i in cookie){
document.cookie = `${
i}=beybey;expires=${
guoqu}`
}
}
}
// 写cookie
function setCookie(key,value,expires){
//expires 有效期
if(typeof expires === "number"){
let date = new Date();
date.setDate(date.getDate()+expires)
document.cookie = `${
key}=${
value};expires=${
date}`;
}
else{
document.cookie = `${
key}=${
value};expires=${
expires}`;
}
}
cookie,localStorage和sessionStorage之间的区别是什么?
- cookie:操作麻烦,需要大量的字符串处理。兼容性好,数据的生命周期可以灵活地设置。
- localStorage:相对于cookie来说兼容性稍差。数据的生命周期是永久性存储。
- sessionStorage:数据生命周期在会话期(在当前标签页中),其余的所有特性都类似于localStorage
闭包:闭包就是在外层函数里嵌套一个内层函数,内层函数作为外层函数return数据的返回值。外层函数是自调用函数,并且将自身的返回值(也就是内层函数本身)赋值给一个变量。在JS执行环境下文中调用该变量就等价于调用了内层函数,并且在内层函数中可以访问到外层函数的局部变量又并且外层函数的局部变量不会被多次声明,此时就形成了一种闭包的写法。
-
好处1:可以将全局变量变为局部变量,减少全局作用域的污染。
-
好处2:外层函数中的局部变量除了调用内层函数以外,是无法进行修改或是获取的。
-
坏处1:因为闭包会破坏掉JS的垃圾回收机制清除闭包内局部变量的行为,所以有内存泄漏的危险。
-
造成内存泄漏的原因:全局变量 dom节点 定时器或回调函数 闭包
GIT:版本控制系统
- git init 初始化仓库
- git status 查看整个仓库的状态
- git add -A 将工作区所有文件提交到缓冲区
- git commit -m “注释” 将缓冲区所有文件提交到版本库
- git diff 文件名 对比文件
- git checkout – 文件名 将某一个文件的修改撤回至与上一次工作区相一致的情况
- git log 查看提交日志
- git reflog 查看提交日志(包含回退操作)
- git reset --hard 版本号 将工作区调整到某一个版本上
- ssh-keygen -t rsa -C “你的邮箱” 导出公钥和私钥
- git commit -am “注释” 将所有工作区内修改的文件绕过缓冲区直接向版本库进行提交
- git push 将本地版本库内的内容同步到远程库中
- git clone 将远程库克隆到本地
- git pull 将远程库内的内容同步到本地版本库中
简易的命令行入门教程:
- Git 全局设置:
git config --global user.name “可乐不加冰”
git config --global user.email “[email protected]”
- 创建 git 仓库:
mkdir project
cd project
git init
touch README.md
git add README.md
git commit -m “first commit”
git remote add origin [email protected]:xin-zhao/project.git
git push -u origin master
- 已有仓库?
cd existing_git_repo
git remote add origin [email protected]:xin-zhao/project.git
git push -u origin master
svn六个步骤: 查出 提交 更新 比较差异 更新日志 编辑冲突
原型链
JavaScript是面向对象的,每个实例对象都有一个__proto__属性,该属性指向它的原型对象,这个实例对象的构造函数有一个原型属性prototype,与实例的__proto__属性指向同一个对象。当一个对象在查找一个属性的时候,自身没有就会根据__proto__向它的原型进行查找,如果都没有,则向它的原型的原型继续查找,直到查到Object.prototype.__proto__为null,这样也就形成了原型链。