阶段介绍及学习方法
什么是js
JavaScript 的历史
js的组成 *
js的引入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 内部引入js
alert('内部使用js')
</script>
<!-- 外链js -->
<script src="myjs.js"></script>
</head>
<body>
<!-- 行间js -->
<button onclick="alert('我被点击了!')">按钮</button>
</body>
</html>
JavaScript 注释
js入门三部曲
找(谁):要进行操作的元素----标签
加(干什么):给找的元素添加 事件
做(结果):事件触发之后的结果–执行的代码—写在一个函数中(函数就是包含代码的一个代码块)
<script>
// 找 找该div
// alert(document.getElementById('box'));
// 加 做--结果函数
document.getElementById('box').onclick = function(){//函数
alert('上课不要带耳机');
}
</script>
window.onload = function(){}
<script>
window.onload = function(){
document.getElementById('box').onclick = function(){//函数
alert('上课不要带耳机');
}
}
</script>
鼠标一些事件
<script>
window.onload = function(){
// 双击
// document.getElementById('box').ondblclick = function(){
// alert('双击');
// }
// 鼠标移入元素时触发 一次
// document.getElementById('box').onmouseenter = function(){
// console.log('鼠标移入')
// }
// 鼠标移出元素时触发 一次
// document.getElementById('box').onmouseleave = function(){
// console.log('鼠标移出出出')
// }
// 鼠标在元素上移动 不停的触发
// document.getElementById('box').onmousemove = function(){
// console.log('动动动');
// }
// document.getElementById('box').onclick = function(){
// console.log('鼠标点击');
// }
// document.getElementById('box').onmousedown = function(){
// console.log('鼠标按下');
// }
// document.getElementById('box').onmouseup = function(){
// console.log('鼠标抬起');
// }
document.getElementById('box').oncontextmenu = function(){
console.log('右键菜单')
}
}
</script>
<script>
window.onload = function(){
// over方法会冒泡
// document.getElementById('box').onmouseover = function(){
// console.log('来了,老弟!')
// }
// enter不会冒泡
document.getElementById('box').onmouseenter = function(){
console.log('来了,老弟!')
}
}
</script>
变量
在内存的栈当中划分一个单元格,并起名字,将需要的数据,元素等存储到该命名单元格中,方便以后使用。
变量的使用分为两步 1 变量的声明 2 变量的赋值
一次性声明值相同的多个变量 连等
一次性声明多个值不同的变量 用,隔开
一个变量,自始至终都存储同一类型的数据
<script>
window.onload = function(){
// 双击
// document.getElementById('box').ondblclick = function(){
// alert('双击');
// }
// 变量存储box元素 然后利用变量来进行后续程序的编写
// var oBox = document.getElementById('box');
// console.log(oBox)
// var a; //声明变量a
// console.log(a); // undefined 未赋值
// // 赋值 =叫赋值符号 从右向左运算赋值
// a = 10;
// console.log(a);
// var a = 10;//声明并赋值
// 声明多个相同值的变量
var a = b = c = 10;
// 声明多个变量值不同 用,隔开
var x = 10, y = 20, z = 30;
}
</script>
变量的命名规则 *
JavaScript 操作元素内容
表单元素
<script>
window.onload = function(){
var oIn = document.getElementById('txt');
var oTxt = document.getElementById('txt2');
var oSel = document.getElementById('sel');
// 获取表单元素的内容
console.log(oIn.value);
console.log(oTxt.value);
console.log(oSel.value);
// 设置表单元素的内容
oIn.value = '没有手机。。。';
oTxt.value = '没啥想说的...';
oSel.value = 'cn';//将默认选中 进行修改
}
</script>
闭合标签
<script>
window.onload = function(){
var oDiv = document.getElementById('box');
// 获取
// console.log(oDiv.innerText);
// console.log(oDiv.innerHTML);
// 设置
//oDiv.innerText = '除却巫山不是云';
// oDiv.innerHTML = '除却巫山不是云';
// oDiv.innerText = '除却巫山不是云';
// oDiv.innerHTML = '除却巫山不是云';
// 先获取原有内容,然后加上新内容,最后赋值给元素内容
// 3赋值给div《--- 1获取原内容 2+
oDiv.innerHTML = oDiv.innerHTML + ',除却巫山不是云'
}
</script>
js操作标签的属性
<script>
window.onload = function(){
// 获取元素
var oDiv = document.getElementById('box');
// 获取属性值
console.log(oDiv.id);//'box'
console.log(oDiv.title);//'haha'
// console.log(oDiv.class);//undefined
console.log(oDiv.className);//'div1'
// 自定义属性无法通过该方法来获取和设置
console.log(oDiv.aaa);//undefined
// 设置属性值
oDiv.id = 'bbox';
oDiv.title = 'heihei';
oDiv.className = 'div2';
}
</script>
.操作符和[]操作符
二者是等价的,凡是用.的地方都可以改写为[],但写法不同 如 div的id , oDiv.id 点后边直接跟已知的属性名
中括号中 要写属性名,必须是字符串形式 就是用引号包裹,凡是写在[]中不带引号的都当做变量
为什么要使用[]当你需要改变的属性或其他存储在一个变量中时 只能[]
<script>
window.onload = function(){
var oDiv = document.getElementById('box');
//.操作符后边是已知的属性名
console.log(oDiv.id)
// 当使用[]时 内部属性名必须用引号包裹
// console.log(oDiv['id']);
var a = 'id';
console.log(oDiv[a]);
}
</script>
js操作行间样式
js是一种弱语言,数据类型也是弱类型。js的数据类型分为6类
typeof 打印数据类型
Number数字类型
整数,浮点数,负数
8进制:以0开头,后续的数字不超过7,识别为8进制。但是打印时自动转换为10进制
16 进制:以0x开头
特殊数字类型 :NaN Not a Number 不是一个数字, Infinity 无限, 小数存储近似值
<script>
// 整数
var num = 10;
console.log(num);
// typeof 打印数据类型的
console.log( typeof num);
// 浮点数
var num1 = 3.1415926;
// 负数
var num2 = -12.34;
// 8进制 0 1 2 3 4 5 6 7
var num3 = 017;//8进制 15
var num4 = 094;//10进制 94
console.log(num3);
console.log(num4);
// 16进制 0 1 2 3 4 5 6 7 8 9 A B C D E F 10
var num5 = 0x1F4C;//8012
console.log(num5);
// 特殊数字类型
console.log('你' - 10);//NaN Not a Number 不是一个数字
console.log(10 / 0);//Infinity 无限
console.log(0.1 + 0.2);//0.30000000000000004
console.log(0.07 * 100);//7.000000000000001
// 计算机最终存储数据时都是2进制来存储的,所以对于某些小数 是存储了一个近似值
</script>
string类型
字符串:文本,数字都作为字符串。用单引号或双引号包裹。
字符串长度方法:str.length;
通过下标获取字符串中的某个字符:str.charAt(下标) str[下标] ie7+
通过表单的value获取的内容都为字符串
<script>
window.onload = function(){
var str = 'abc';
var str1 = '123';
var phone = '15412341234';
console.log(typeof str1);
var oIn = document.getElementById('txt');
var oBtn = document.getElementById('btn');
oBtn.onclick = function(){
console.log(typeof oIn.value);
}
var str = 'abcdefghijk';
console.log(str.length);
// 任何的下标都是以0开始的,第一个字符的下标是0
// a b c d e f g
// 下标 0 1 2 3 4 5 6
console.log(str.charAt(4));
console.log(str[4]);
}
</script>
boolean 布尔值
null 和 undefined
<script>
// boolean
var bl = true;
var bl1 = false;
console.log( typeof bl);
console.log( 10 > 20);//false
// null
var a = null;
var oDiv = document.getElementById('box');
console.log(oDiv);
console.log( typeof oDiv);
// undefined
var b;
console.log(b, typeof b);//undefined "undefined"
</script>
基本类型和引用类型的区别—null空对象 实际上是一个空对象指针
object类型— object array function
object 创建方式 实例化创建 和字面量创建
以{键1:值1,键2:值2,。。。。。}
获取某一个键的值
obj.name 对象名.键名
修改某一个键的值
obj.age = 30 对象名.键名 = ‘ 新键值’
添加一个新的键值对
obj.work = ‘player’ 对象名.新键名 = ‘键值’
<script>
// 对象类型 object
// 创建方式2种 实例化对象 字面量创建
// 实例化对象创建
var obj = new Object();//没有具体属性的空对象 不是null
console.log(obj, typeof obj);
// 字面量创建对象
var obj = {
name:'joth',
age:20,
sex:'male',
}
// 获取某一个键的值
console.log(obj.name);
// 修改某一个键的值
console.log(obj);
obj.age = 21;
console.log(obj);
// 添加一个新的键值
obj.work = 'eater';
console.log(obj);
</script>
function函数
声明函数包裹代码块—声明时函数内部的代码是不执行的
调用函数来执行—通过函数名来调用执行
当使用函数名 加() 代表调用执行 不加 直接写函数名 代表函数本身
<script>
function aa(){//函数的声明 这只是定义了函数 函数内部的代码并不执行
console.log('aa');
}
// 函数需要调用执行---通过函数名来调用
aa();
</script>
数组Array
用[数据项1,数据项2,数据项3,。。。。。]
数组中可以存储任意类型的数据,但是 同一个数组存储同一类数据
数组长度 数组.length
可以通过下标 访问数据组中的某一项对应的数据 下标从0开始
<script>
// 实例化对象创建数组
var arr = new Array();
console.log(arr, typeof arr);
// 字面量创建数组
var arr = ['a',10,false,[1,2,3],{name:'rose',age:18},null, undefined]
// 数组中可以存储任意类型的数据,但是 数组最好是 同一个数据存储同一类数据
var arr2 = [1,2,3,4,5,6]
var arr3 = ['aaa','bbb','ccc']
// 有长度
console.log(arr2.length);
// 可以通过下标 访问数据组中的某一项对应的数据 下标从0开始
console.log(arr2[0]);//1
console.log(arr2[3]);//4
</script>
通过typeof返回的值
数据类型的转换—强制数据转换
其他类型转换为数字
Number(其他类型):只能是 纯数字字符串,空字符串和布尔值可以转换其他数据均不能转换为数字
<script>
var str = '12';
console.log(str);
console.log(Number(str));
var str = '100px';
console.log(Number(str));//NaN
console.log(Number('a123'));//NaN
console.log(Number(''));//0 ''===>false===>0
console.log(Number(false));//0
console.log(Number(true));//1
console.log(Number(null));//0 null ===> false ===>0
console.log(Number(undefined));//NaN
console.log(Number(070));// 56
console.log(Number(090));// 90
// 引用类型的转换
console.log(Number(function aaa(){console.log(111)}));//NaN
console.log(Number([1,2,3]));//NaN
console.log(Number([10]));//10 数组只有一个数据,且该数据是数字或纯数字字符串是 可以转换为数字
console.log(Number([]));//0 空数组 可以转换为0
console.log(Number({}));//NaN 不是空对象 空对象是 null
console.log(Number({name:'joth',age:20}));//NaN
</script>
parseInt和parseFloat
parseInt 将非空字符串转为整型数字,parseFloat 将非空字符串转为浮点型数字
尽可能多的去识别数字字符串,当遇到不是数字字符时 结束 然后返回数字
parseInt转换带小数的字符串时 会将小数部分直接舍弃
parseInt 有第二个参数,用来说明以什么进制来识别要转换的内容,最后输出10进制的值
parseFloat 在转换时 有小数则保留小数
<script>
console.log(parseInt(false));//NaN
console.log(parseInt(''));//NaN
console.log(parseInt(null));//NaN
console.log(parseInt(undefined));//NaN
console.log(parseInt('100px'));//100
console.log(parseInt('100px32'));//100
console.log(parseInt('a123'));//NaN
// 取整
console.log(parseInt('12.976'));//12
console.log(parseInt(12.14));//12
// parseInt的第二个参数 用来说明数据的进制 2 - 32
console.log(parseInt('070',10));// 统一用10进制来识别要转换的数据 得到70
console.log(parseInt('01101',2));// 统一用2进制来识别要转换的数据 得到13
console.log(parseInt('1fd3',16));// 统一用16进制来识别要转换的数据 得到8147
// parseFloat 转换为保留小数的数字
console.log(parseFloat('12.976'));//12.976
console.log(parseFloat('12.111'));//12.111
console.log(parseFloat('12'));//12
console.log(parseFloat('asdf'));//NaN
// 当转换完成 它不是一个数字 那么 就返回true
console.log(parseFloat('asdf') == NaN);//false
// NaN 不等于NaN
</script>
如果要判断 不是一个数字然后返回为真,不能使用 某个数据转换==NaN 的方式
NaN不等于NaN
isNaN用来判断不是一个数字则返回真
确定不是一个数字
isNaN 本身没有做任何判断 它去调用了Number方法 如果该数据Number可以转换为数字 那么就是一个数字则返回false 如果Number不能转换,那么就不是一个数字则返回true
console.log(isNaN('aaa'));//true
console.log(isNaN('123'));//false
其他类型数据转字符串
String(数据或变量)
数据或变量.toString(radix);
<script>
var num = 10;
var b = false;
var n = null;
var n1 = NaN;
var un = undefined;
var arr = [];
var arr1 = [10];
var arr2 = [1,2,3];
var obj = {};
var obj1 = {
name:'joth',
age:20
}
var fn = function(){
console.log('aaa')
}
// String()
console.log(String(num));//'10'
console.log(String(b));//'false'
console.log(String(n));//'null'
console.log(String(n1));//'NaN'
console.log(String(un));//'undefined'
console.log(String(arr));//''
console.log(String(arr1));//'10'
console.log(String(arr2));//'1,2,3'
console.log(String(obj));//'[object Object]'
console.log(String(obj1));//'[object Object]'
console.log(String(fn));//
// toString()
console.log(num.toString());//'10'
console.log(b.toString());//'false'
// console.log(n.toString());//报错
console.log(n1.toString());//NaN
// console.log(un.toString());//报错
console.log(obj1.toString());
// 转换为各种进制的字符串
var num2 = 18;
console.log(num2.toString(2));//10010'' 18的二进制字符串
console.log(num2.toString(8));//'22' 18的8进制字符串
console.log(num2.toString(16));//'12' 18的16进制字符串
// 例如 我现在计算了一个颜色 14673456 ===》
var nn = 14673456;
console.log('#' + nn.toString(16));
</script>
其他类型转换为布尔值
<script>
var str = '';
var num2 = 0;
var b = false;
var n = null;
var n1 = NaN;
var un = undefined;
var num = 10;
var arr = [];
var arr1 = [10];
var arr2 = [1,2,3];
var obj = {};
var obj1 = {
name:'joth',
age:20
}
var fn = function(){
console.log('aaa')
}
// Boolean
console.log(Boolean(str));//false
console.log(Boolean(num2));//false
console.log(Boolean(b));//false
console.log(Boolean(n));//false
console.log(Boolean(n1));//false
console.log(Boolean(un));//false
console.log(Boolean(arr));//true
console.log(Boolean(obj));//true
console.log(arr);
console.log(obj);
</script>
运算符
算术运算符
一元运算符 ++自增 --自减
二元运算符 + - * / %(取余) 求模
<script>
// var a = 10;
// var b = a++;
// console.log(a, b);// 11 10
// var a = 10;
// var b = --a;
// console.log(a, b);//9 9
var a = 10;
var b = 10;
console.log(a++ + --a + b-- + b++ + a--); //49
// 10 + 10 + 10 + 9 + 10
// b10 a9
console.log(a);//9
console.log(b);//10
// +
console.log('a' + 10);//'a10'
console.log('12' + '13');//'1213'
console.log(10 + true);//11
console.log(10 + undefined);//NaN
console.log(['1'] + 10);//
console.log([1,2,3] + 10);//
// -
console.log('100' - 10);//90
console.log(true - 10);//
console.log('aaa' - 10);//NaN
console.log('100px' - 10);//NaN
var n = 17;
console.log(n % 3);//2
var n = 10;
console.log(n % 5);//0
console.log(1 % 13);//1
</script>
赋值运算符
= 赋值 += -= *= /= %=
a = a + 5 <==> a += 5 等价
<script>
var a = 10;
// a = a + 5;
a += 5;
console.log(a);//15
// oDiv.innerHTML = oDiv.innerHTML + 'aaa';
// oDiv.innerHTMl += 'aaa';
var a = 13;
a %= 5;
console.log(a);//3
</script>
比较运算符
> < >= <= ==等于 !=不等于 =全等 ! 不全等 返回布尔值
== 进行隐式转换 然后进行值比较 === 将数据类型和值一起比较都要相等
<script>
console.log(10 > 2);//true
console.log(10 == '10');//true
console.log(10 === '10');//false
console.log(10 != '10');//false
console.log(10 !== '10');//true
console.log('100' > '12');//false
// '1' '2' 比较第一位的字符串的ASCII码
// 33 > 34 false
// 'a' ---> 97 ---> 1100001 所以英文适合编程
//
</script>
逻辑运算符
<script>
console.log(false && true);//false
console.log(10 > 3 && 12 > 100);//false
// true && false ==>false
console.log(10 > 3 || 12 > 100);//true
// var a = 0;
// console.log(a && ++a);//0
// 短路运算
// 短路与
// 当第一项数据转换为布尔值时,为假,则返回第一项数据,否则返回第二项数据
console.log('' && 10);//''
console.log('aaa' && 10);//10
// 短路或
// 当第一项数据转换为布尔值时,为真,则返回第一项数据,否则返回第二项数据
console.log('' || 10);//10
console.log('aaa' || 10);//'aaa'
console.log(!false);//true
console.log(!(10 > 100));//true
</script>
三目运算符
运算符的优先级
隐式数据类型转换
程序设计的三大结构:
顺序结构 : 程序自上而下 顺序执行。
条件选择结构(分支结构)
在程序设计中 最好不要出现if的嵌套 干脆最好别用if 一般两分支 直接用三目 多分支 switch
<script>
// 如果明天下雨 我去看电影
// if(下雨){看电影}
// var rain = true;
// if(rain){console.log('watch movie')};
// 当只有一个条件满足的情况时 后续的{}可以省略
// if(rain) console.log('watch movie');
// 如果明天不下雨 我去踢球
// if(不下雨){踢球}
// if(!rain) console.log('play football');
// if() ..是当()内的值或表达式结果为true时执行...
// var rain = false;
// if(!rain) console.log('watch movie');
var rain = true;
if(rain){
// 当条件为真时执行的代码块
console.log('watch movie!');
}else{
// 当条件为假时执行的代码块
console.log('paly football');
}
// 多分支 ifelse 嵌套
// 成绩 小于60 一顿暴打 60-70 奖励黄冈试卷 70 - 80 奖励三年高考 80-90 100元 90--100 奖励ipad
var g = 100;
if(g >= 90 && g <=100){
console.log('iPad');
}else if(g >=80 && g < 90){
console.log('$100');
}else if(g >= 70 && g < 80){
console.log('三年高考');
}else if(g >= 60 && g < 70){
console.log('huanggang test');
}else if(g < 60 && g >= 0){
console.log('一顿暴打')
}else{
console.log('成绩有误');
}
// 在程序设计中 最好不要出现if的嵌套 干脆最好别用if 一般两分支 直接用三目 多分支 switch
switch case; 多分支
<script>
var like = '100';
switch(like){//case判断必须是一个常量值,不能使用表达式
case '1':
console.log('eat');
break;
case '2':
console.log('sleep');
break;
case '3':
console.log('play mGame');
break;
case '4':
console.log('play code');
break;
default:
console.log('fa dai');
}
// 成绩 小于60 一顿暴打 60-70 奖励黄冈试卷 70 - 80 奖励三年高考 80-90 100元 90--100 奖励ipad
// 100 90-99 80-89 70-79 60 -69
// 10 9 8 7 6 default
var g = 42;
switch(parseInt(g / 10)){
case 10:
console.log('满分出国游');
break;
case 9:
console.log('$300');
break;
case 8:
console.log('$100');
break;
case 7:
console.log('黄冈试卷');
break;
case 6:
console.log('三个补习班');
break;
default:
console.log('竹板炒肉');
}
</script>
DOM 元素获取
<script>
window.onload = function(){
// 通过标签获取元素
// var oDiv object 一个对象 aLi array sClass string bDown boolean
// var aLi = document.getElementsByTagName('li');//整个文档下的所有li
// console.log(aLi);//获取到的是一个类似于数组的元素集合
// // 先获取父级元素 再在父级元素中获取子元素
// var oList = document.getElementById('list');
// var aLi = oList.getElementsByTagName('li');
// var aLi = document.getElementById('list').getElementsByTagName('li');
// 当标签获取元素后 可以通过下标得到其中的某一个元素
// var oUl = document.getElementsByTagName('ul')[1];
var aLi1 = document.getElementsByTagName('ul')[0].getElementsByTagName('li');
var aLi2 = document.getElementsByTagName('ul')[1].getElementsByTagName('li');
console.log(aLi1);
console.log(aLi2);
var aP = document.getElementsByClassName('p1');
console.log(aP)
// aLi1.style.background = 'pink'; //因为aLi1是一个元素集合 设置背景颜色 要针对元素也就是元素集合中的每个元素
aLi1[0].style.background = 'pink';//通过下标获取每个元素,但是当元素很多时 不可能人为1个1个的去 获取设置 需要交给程序来进行 循环遍历每个元素去添加样式
aLi1[1].style.background = 'pink';
aLi1[2].style.background = 'pink';
aLi1[3].style.background = 'pink';
}
</script>
循环结构(循环遍历,迭代)
for(循环变量初始值;边界判断条件;循环变量自增){} 最常用
<script>
for(var i = 0; i < 10; i++){
console.log(i);
}
// 1 i = 0 i< 10 true 打印0 i++ i==>1
// 2 i = 1 1 < 10 true dy1 i++ i==>2
// 3 i = 2 2 < 10 true dy2 i++ i==>3
// .....
// 10 i = 9 9< 10 true dy 9 i++ i==>10;
// 11 i = 10 10 < 10 false exit
// 其他写法
// var j = 0;
// for(;j < 10;){
// console.log(j);
// j++;
// }
// 循环嵌套
for(var i = 0; i < 5; i++){
for(var j = 0; j < 4; j++){
console.log('j:' + j);
}
console.log('i:' + i);
}
// 1 i = 0 j 0-->4 dyj 0 1 2 3 dyi 0 i++ i==>1
// 2 i = 1 j 0---4 dyj 0 1 2 3 dyi 1 i++ i==>2
// ....
// 通过二重循环打印 * 构成的矩形
for(var i = 0; i < 4; i++){//外层循环控制行数并打印 换行
for(var j = 0; j < 10; j++){//内层循环 每行循环之后 内存循环5次 打印5个*
document.write('*');
}
document.write('
');
}
</script>
<script>
//圆点组成直角三角形
for(var i = 0; i < 6; i++){
for(var j = 0; j < i + 1; j++){
document.write('●');
}
document.write('
');
}
// 1 i = 0 j < 1 j 0 i++ i = 1
// 2 i = 1 j < 2 j 0 1 i++ i = 2
// 3 i = 2 j < 3 j 0 1 2 i++ i = 3
// ....
//圆点组成等腰三角形
var n = 10;
for(var i = 0; i < n; i++){//行
// 第一个内层循环 循环空格
for(var k = n - 1 - i; k >=0; k--){
oDiv.innerHTML += ' '
}
// 第二个内层循环 循环打印圆
for(var j = 0; j < i * 2 + 1; j++){
oDiv.innerHTML += '●';
}
oDiv.innerHTML += '
';
}
</script>
<script>
window.onload = function(){
var aLi = document.getElementsByTagName('li');
// aLi[0] aLi[1]
// console.log(aLi);
for(var i = 0; i < aLi.length; i++){
aLi[i].style.background = 'pink';
}
// 希望 奇数行 粉色 偶数行 purple紫色
}
</script>
var arr = ['a','b','c','d','e','f','g'];
// 数组的每一项数据都有下标 数组可以通过length求长度
for(var i = 0; i < arr.length; i++){
console.log(arr[i]);
}
for in 常用 专门用来循环对象
// 对象类型的遍历
var obj = {
name:'joth',
age:20,
sex:'male'
}
console.log(obj.length);//undefined
// 对象类型的数据 没有长度 而且 每个键值对 没有下标 它的数据访问 键名 不能用for循环
// for in 专门用来循环 对象的
for(var key in obj){
console.log(key + '---' + obj[key]);
}
while(){} 偶尔
do {} while() 基本没用
<script>
// var i = 0;
// while(i < 4){
// console.log(i);
// i++;
// }
// var i = 0;
// do{
// console.log(i);
// i++
// }while(i < 4);
// var i = 11;
// while(i < 10){//完全不满足条件 就直接结束了
// console.log(i);
// i++;
// }
// var i = 11;
// do{
// console.log(i);
// i++;
// }while(i < 10);//后判断 即便不符合条件 那么也要执行一次
// var i = 4;
// while(i > 0){//死循环
// console.log('haha');
// i++;
// }
</script>
循环当中的 continue 和 break;
<script>
// 打印前100个自然数中的所有偶数
// for(var i = 1; i <= 100; i++){
// if(i % 2 == 1){//当 满足条件 就跳过该次循环 那么该次循环中的后续代码就都不执行了 直接进入下一次循环
// continue;
// }
// console.log(i);
// }
// 当i达到50的时候 就中断整个循环 后续的循环都不再执行
// for(var i = 1; i <=100; i++){
// if(i > 50){
// break;
// }
// console.log(i);
// }
// 计算前100个自然数中的所有素数: 只能被1和它本身整除的数叫素数 1既不是素数也不是合数
for(var i = 2; i <= 100; i++){
var flag = true;// 当flag为真 就说明是素数
for(var j = 2; j < i; j++){
if(i % j == 0){
flag = false;
break;
}
}
if(flag){
console.log(i);
}
}
//1 i = 2 flag = true dy 2
//2 i = 3 flag = true dy 3
//3 i = 4 flag = true 4 % 2 == 0 flag = false; flag 为假 不打印
//4 i = 5 flag = true 5 % 2 3 4 flag = true dy 5
//5 i = 6 falg = true 6 % 2 == 0 falg = false break; flag 假 不打印
// ....
</script>
作用域及作用域链
<script>
// 全局作用域
// var a = 10;//全局作用域下声明的变量 全局变量
// function fn(){
// console.log(a + 10);
// }
// fn()
// function fnn(){
// a = 'aaa';//使用了全局变量a 导致了全局变量的污染
// console.log(a);
// }
// fnn();
// fn();
// 局部作用域
// function fn(){
// var a = 100;//函数fn作用域下的局部声明的变量 局部变量 它的作用域 使用范围就是函数fn内部
// console.log(a);
// }
// fn();
// console.log(a);//a is not defined( 程序报错---a压根就没有 没有声明) undefined(是js的一种数据类型 表明变量已经声明了但没有赋值)
// function aa(){
// function fn(){
// console.log('fn');
// }
// fn();
// }
// aa();
// fn();//局部函数fn 在aa范围以外 不能调用
var a = 10;//全局变量
function fn(){
var a = 100;//在函数内部重新声明了一个a 这时在fn函数内使用a都是使用局部变量
a++;
console.log(a);
}
function fnnn(){
var ccc = 10;
function fnn(){
a++;//该函数中没有声明过局部变量a 这时就使用全局变量a
console.log(a);
}
}
fn();//101
fnn();//11
</script>
预解析(变量提升)
当浏览器在执行js代码之前,会进行一个预解析的操作,包含且不至以下两步
- 预解析 程序还没开始执行 然后会悄悄的找你整个代码中的所有的var 找到之后将你定义的 变量名预先存储到 内存栈中 var a 当程序开始真正执行 时再做a=10;
- 函数在执行预解析时 找到所有声明的函数 function 将函数所有的代码块 全部预先存储到内从中,所以 函数 先调用再声明是没用问题的 也就是声明的过程在程序执行之前 已经帮你做好了
- 函数内部可以看作是一个小的区域,有自己的预解析
<script>
// 变量的预解析
console.log(a);//undefined 没有报错
var a = 10;
// 函数预解析后 在任何位置都可以调用函数
fn();
function fn(){
console.log('fn');
}
</script>
函数返回值
函数在调用执行后 希望在函数外部使用函数计算后的结果,这时函数就要通过返回值的形式来将结果返回出函数。
<script>
// 我要在1-100的和的基础上 乘以一个值 目的这个1-100的和 我需要使用
// function sum(num){
// var result = 0;
// for(var i = 0; i <= num; i++){
// result += i;
// }
// // console.log(result);
// // 当函数外部需要使用函数的计算结果
// return result;//将结果返回出去 5050
// }
// // console.log(sum(100));
// var he = sum(100);// 声明一个变量 用来存储 函数返回的结果
// console.log(he)
// 函数没有写明return 返回值 默认就返回 undefined
// function fn(){
// var a = 10;
// }
// console.log(fn());
// return之后的代码将不再执行 ,所以 return可以作为函数中断来使用
// function fn(){
// console.log('111');
// return;//直接写一个return的作用是中断函数的执行
// console.log('222');
// }
// fn();
// 函数一次只能返回一个数据,但当我想返回多个时 该怎么办?
// function fn(){
// var a = 10;
// var b = 20;
// return a, b;
// }
// console.log(fn());
// 当你想返回多个值时 return只能返回一个数据 利用 数组或对象来返回
// function fn(){
// var a = 10;
// var b = 20;
// return [a, b];//返回数据的形式
// }
// // console.log(fn());
// var aa = fn()[0];
// var bb = fn()[1];
// console.log(aa, bb);
function fn(){
var a = 10;
var b = 20;
return {num1: a, num2: b};
}
var obj = fn();
console.log(obj);
console.log(obj.num1, obj.num2);
</script>
获取非行间样式
function getStyle(el, attr){//el传入要获取样式的元素 attr 要获取样式的属性名
return el.currentStyle ? el.currentStyle[attr] : getComputedStyle(el)[attr];
// if(el.currentStyle){
// return el.currentStyle[attr];
// }else{
// return getComputedStyle(el)[attr];
// }
}
函数封装及复用—购物车
<script>
window.onload = function(){
var aLi = document.getElementsByTagName('li');
for(var i = 0; i < aLi.length; i++){
shopCar(aLi[i]);
}
/*
// 通过循环将shopCar函数调用执行了 5遍
shopCar(aLi[0]);
shopCar(aLi[1]);
shopCar(aLi[2]);
shopCar(aLi[3]);
shopCar(aLi[4]);
*/
function shopCar(el){
var add = el.getElementsByTagName('button')[1];//增加按钮
var reduce = el.getElementsByTagName('button')[0];//减少按钮
var oSpan = el.getElementsByTagName('span')[0];//数量span
var oEm = el.getElementsByTagName('em')[0];//单价
var oI = el.getElementsByTagName('i')[0];//小计
add.onclick = function(){
var n = parseInt(oSpan.innerHTML);//获取数量转换为数字
n++;//每点击一次 数量增加1
oSpan.innerHTML = n;//将增加后的数量 显示到span中去
calc();
}
reduce.onclick = function(){
var n = parseInt(oSpan.innerHTML);//获取数量转换为数字
n--;//每点击一次 数量增加1
if(n <= 0){
n = 0;
}
oSpan.innerHTML = n;//将增加后的数量 显示到span中去
calc();
}
function calc(){
var count = parseInt(oSpan.innerHTML);//获取数量
var price = parseFloat(oEm.innerHTML);//获取单价
oI.innerHTML = (count * price).toFixed(2);//计算小计 四舍五入保留2位小数
}
}
// 完善 显示总数量和总价
}
</script>
定时器
<script>
// 延时定时器
setTimeout(function(){
console.log('哈哈哈');
},2000)
// 间隔定时器
setInterval(function(){
console.log('呵呵呵');
},1000)
</script>
清除定时器
异步和同步问题
异步 asyn:程序执行时几件一起做
同步syn:程序执行时 一件一件排序去做
js是单线程语言,所以在主线程中 执行代码时 直接先执行同步代码,当遇到异步代码时,就将异步代码存放到任务队列去,然后继续执行同步代码,当主线程中的所有同步代码执行完成之后,再去轮询任务队列,将准备完毕的异步代码调回主线程来进行执行。
<script>
window.onload = function(){
var aLi = document.getElementsByTagName('li');
for(var i = 0; i < aLi.length; i++){
aLi[i].onclick = function(){//事件驱动函数是一个异步函数
console.log(i);//4
}
}
}
for(var i = 0; i < 4; i++){
setTimeout(function(){//凡是回调函数 都为异步执行
console.log(i);
},0)
}
</script>
匀速运动函数封装
//运动基础
oBtn.onclick = function(){
clearInterval(timer);//每次点击将上次的定时器清除,目的防止多次点击 叠加后速度变快
timer = setInterval(function(){
var cur = parseInt(getStyle(oDiv, 'left'));//当前div的left值
//在当前值上 加上 步长 存放在speed中
var speed = cur + 7;
// 边界限定
if(speed >= 800){
speed = 800;//手动修正该值 强制为 目标值
clearInterval(timer);//清除定时器
}
oDiv.style.left = speed + 'px';//给div赋值 改变div的left值
},20)
}
//封装函数
function linearMove(el,step,target,attr){//el要运动的元素 step步长 每次移动多少像素 target 运动的目标值 attr是要进行运动的属性
clearInterval(timer);
step = parseInt(getStyle(el, attr)) > target ? -step : step;//当当前值小于目标值 则 step 赋值为step 否则 当前值大于目标值 则 step赋值为 -step
timer = setInterval(function(){
var cur = parseInt(getStyle(el, attr));//获取当前属性值
var speed = cur + step;//当前值加步长 计算本次移动到的位置
// 当step 是正值 那么元素运动到大于等于目标值时 判断条件为真 需要停止
// 当step 是负值 那么元素运动到小于等于目标值时 判断条件为真 需要停止
if((step > 0 && speed >= target) || (step < 0 && speed <= target)){
speed = target;
clearInterval(timer);
}
el.style[attr] = speed + 'px';
}, 20)
}
数学对象 Math
数学对象就是指 在程序中进行一些相对的数学运算:
<script>
console.log(Math.abs(-100));
console.log(Math.sin(30 * Math.PI / 180));//Math下的三角函数中使用的不是角度 而是 弧度 弧度 = 角度*pi/180;
console.log(Math.ceil(2.134));// 3
console.log(Math.ceil(-2.534));// -2
console.log(Math.floor(2.134));// 2
console.log(Math.floor(-2.534));// -3
console.log(Math.round(2.134));// 2
console.log(Math.round(2.534));// 3
console.log(Math.sqrt(81));// 9
console.log(Math.pow(9,3));// 729
console.log(Math.max(1,2,3,4,5,6,7,8,9,100));// 100
console.log(Math.min(1,2,3,4,5,6,7,8,9,100));
console.log(Math.max);
console.log(Math.random());
</script>
最重要的一个 random 随机数(0 — 1 之间 的随机浮点数,包含0,不包含1)
<script>
// 3-24 之间的随机数
// Math.floor((max - min + 1) * Math.random() + min);
var n = Math.floor((24 - 3 + 1) * Math.random() + 3);
console.log(n)
</script>
js中的对象
日期时间对象
<script>
// 创建一个日期时间对象
var oDate = new Date(); //data 数据
console.log(oDate);
// 获取 年 月 日 周几 时 分 秒
var y = oDate.getFullYear();
var m = oDate.getMonth() + 1;// 0-- 11
var d = oDate.getDate();
var w = oDate.getDay();
var h = oDate.getHours();
var mi = oDate.getMinutes();
var s = oDate.getSeconds();
var week = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'];
console.log(y + '年' + toDouble(m) + '月' + toDouble(d) + '日' + week[w] + toDouble(h) + ':' + toDouble(mi) + ':' + toDouble(s))
function toDouble(num){
return num < 10 ? '0' + num : '' + num;
}
</script>
时间戳 获取从1970年1月1日 0:0:0 到当前日期时间的毫秒数
<script>
// 时间戳
var oDate = new Date();
// console.log(oDate.getTime());
// 设置日期时间
// 设置一个完整的日期时间
// var oDate1 = new Date('2020-10-1 0:0:0');
// var oDate1 = new Date('2030,10,1,0:0:0');
// var oDate1 = new Date(2030,10 - 1,2,0,0,0);
// console.log(oDate1);
// oDate.setFullYear(2030);
// // setMonth setDate setMinutes setHours
// console.log(oDate)
// 几种不同的时间日期的输出格式
console.log(oDate.toString());//打印oDate Tue Jul 21 2020 11:39:59 GMT+0800 (中国标准时间)
console.log(oDate.toLocaleDateString());//2020/7/21
console.log(oDate.toLocaleString());//2020/7/21 上午11:39:59
console.log(oDate.toLocaleTimeString());//上午11:39:59
</script>
momentjs 时间格式化插件
<script>
// var now = moment();
// console.log(now);//Moment对象
var now = moment().format('YYYY年 MM月 DD日 星期d hh:mm:ss');
console.log(now);
//设置一个日期成为moment对象
var end = moment('2030-10-01',['YYYY-MM-DD']);
console.log(end);
// 通过对象方式来设置moment对象
var time = moment({
year:'2030',
month:'9',
day:'12',
hour:'14',
minute:'45',
second:'55'
})
console.log(time);
// 获取时间戳
var oDate = new Date();
console.log(oDate.getTime());
console.log(moment().valueOf());
// moment对象和原生 时间转换
// 原生日期时间转换为 moment对象
console.log(moment(oDate))
// moment对象转换为原生日期时间
console.log(moment().toDate());
// moment的获取年月日等
console.log(moment().year());
console.log(moment().month() + 1);
// get方法来获取
console.log(moment().get('year'));
// set方法来设置
console.log(moment().set('year',2030).toDate());
// isBefore()查询一个日期是否在另一个日期之前
console.log(moment('2020-7-19').isBefore(moment()));
// isAfter()查询一个日期是否在另一个日期之后
console.log(moment('2020-7-19').isAfter(moment()));
// isSame()查询一个日期是否和另一个日期相同
// isBetween()查询一个日期是否在两个日期之间
console.log(moment().isBetween('2020-7-1','2020-7-25'));
// isLeapYear()//测试是否为闰年
console.log(moment().isLeapYear());
</script>
字符串对象
实例化创建
字面量创建
字符串方法
<script>
var str = 'A0abcdefg';
console.log(str.charAt(0));//'a'
console.log(str.charCodeAt(0));//97 ASCII码 0---48 a---97 A---65
var str = 'abcdefghijklmn';
console.log(str.indexOf('e'));// 4
console.log(str.indexOf('z'));// -1
console.log(str.indexOf('ijk'));// 8 返回的是i的下标
console.log(str.indexOf('ijl'));// -1
var str = 'abcabcabcabc';
console.log(str.indexOf('a'));//0
console.log(str.lastIndexOf('a'));// 9
</script>
<script>
var str = 'abcdefghijklmn';
console.log(str.length);
// substring()
console.log(str.substring(3,7));//defg
console.log(str.substring(3));//从3开始截取完defghijklmn
console.log(str.substring(8,2));//如果起始大于结束 会自动互换位置cdefgh
console.log(str.substring(-3,3));//如果某个值为负数 会自动转换为0 abc
console.log('--------------------------------------------------');
// slice()
console.log(str.slice(3,7));//defg
console.log(str.slice(3));//从3开始截取完defghijklmn
console.log(str.slice(8,2));//'' 不支持下标互换位置
console.log(str.slice(-3,3));//'' 起始不支持负数
console.log(str.slice(3,-3));//defghijk 当结束下标为负数时 转换 str.length + (-3); 3-11
console.log('--------------------------------------------------');
// substr()
console.log(str.substr(3,3));//def
console.log(str.substr(3));//defghijklmn
console.log(str.substr(-3,3));//起始为负数 str.length + (-3) 从下标为11开始向后截取3个
</script>
// toLowerCase() toUpperCase()
var str = 'aBcDEfGH';
console.log(str.toLowerCase());
console.log(str.toUpperCase());
console.log('--------------------------------------------------');
// split 字符串方法 将一个字符串 通过某种分割符 分割为一个数组
var str = 'a-b-c-d';
var arr = str.split('-');
console.log(arr);
var str = 'abcd';
var arr1 = str.split('');
console.log(arr1);
//http://item.taobo.com/item.html?a=1&b=2&c=&d=xxx&e 获取参数 得到
//{a:“1”,b:“2”,c:“”,d:“xxx”,e:undefined}
/*
var str = 'http://item.taobo.com/item.html?a=1&b=2&c=&d=xxx&e'
var arr = str.split('?');//[http://item.taobo.com/item.html,a=1&b=2&c=&d=xxx&e]
nArr = arr[1].split('&'); //['a=1','b=2','c=','d=xxx','e']
循环遍历nArr 取出每一项 在拆分 然后对应放到一个对象中去
*/
console.log('--------------------------------------------------');
// replace();
var str = '13412340987';
console.log(str.replace(str.substr(3,4),'****'));
console.log('--------------------------------------------------');
// trim(); 删除字符串两端的空格
var str = ' abcd ';
console.log(str);
console.log(str.trim());
数组对象的创建
实例化创建 new Array()
字面量创建 var arr = [];
arr.length 获取数组的长度 (读) 可写 就是修改长度来修改数组的数据项
<script>
var arr = [1,2,3,4,5,6];
console.log(arr.length);
arr.length = 3;
console.log(arr);
arr.length = 0;//清空数组
console.log(arr);
</script>
数组的方法
数组的添加和删除
数组的截取,删除,替换,插入
<script>
var arr = [1,2,3,4,5];
arr.push(100,101,102);//尾部添加
console.log(arr);
var str = arr.pop();//尾部删除 并将删除的数据 返回 存储到 str中
console.log(arr, str);
arr.unshift(-3,-2,-1,0);//头部添加
console.log(arr);
var str1 = arr.shift();//头部删除
console.log(arr, str1);//头部删除 并将删除的数据 返回 存储到 str中
// splice 截取(删除)
var arr = [1,2,3,4,5,6,7];
// var delArr = arr.splice(3,2);
// console.log(arr, delArr);
// 在任意位置添加
// arr.splice(4,0,'a','b','c');
// console.log(arr);
// 替换
arr.splice(3,2,'a','b');
console.log(arr);
</script>
数组的排序
排序算法
冒泡排序法
<script>
var arr = [12,34,76,123,45,2,65,79,1,344,443,556,28];
// 冒泡排序
function bubbleSort(arr){
for(var i = 0; i < arr.length; i++){//外层循环控制比较次数
for(var j = 0; j < arr.length - i; j++){
if(arr[j] > arr[j + 1]){
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
console.log(bubbleSort(arr));
</script>
选择排序法
<script>
var arr = [12,34,76,123,45,2,65,79,1,344,443,556,28];
// 选择排序
function selectSort(arr){
for(var i = 0; i < arr.length; i++){//控制比较次数 控制顺序的固定位置
for(var j = i + 1; j < arr.length; j++){
if(arr[i] > arr[j]){
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
console.log(selectSort(arr));
</script>
递归–快速排序法
<script>
// 快速排序法 是采用了二分法的理念来进行排序
// 取到数组中中间索引对应的值, 建立两个数组 一个左数组 一个右数组
// 进行值的比较 比中间这个值小的 放到左数组 比中间值大的放到右数组
// 进行递归 对左数组 和右数组 继续以上快排函数进行继续操作
// 最后 将 左数组 中间值 和右数组 链接为一个新数组
var arr = [12,34,76,123,45,2,65,79,1,344,443,556,28];
function qSort(arr){
if(arr.length <= 1){//当数组中的长度为 1 就代表该数组中只有一个数
return arr;//直接返回该数组
}
var mIndex = Math.floor(arr.length / 2);//求中间下标
var mVal = arr.splice(mIndex,1);//截取出中间下标对应的值
var lArr = [];//左数组
var rArr = [];//右数组
for(var i = 0; i < arr.length; i++){//循环截取掉中间值的剩余的数据项
if(arr[i] > mVal){//如果该值 比 中间值大
rArr.push(arr[i]); //添加到右数组
}else{
lArr.push(arr[i]); //否则 添加到左数组
}
}
return qSort(lArr).concat(mVal,qSort(rArr));//返回 进行递归 然后 连接 左数组连接中间值 和 右数组
}
console.log(qSort(arr));
</script>
js提供的排序方法
<script>
// var arr = [12,34,76,123,45,2,65,79,1,344,443,556,28];
// var nArr = arr.sort(function(a, b){
// // return a - b;//正序
// return b - a; //倒序
// })
// console.log(nArr);
var arr3 = [
{"date":"2018-08-01", "DIU": 1209, "country": "US"},
{"date":"2018-08-02", "DIU": 680, "country": "GB"},
{"date":"2018-08-01", "DIU": 2311, "country": "CN"},
{"date":"2018-08-02", "DIU": 879, "country": "US"},
{"date":"2018-08-03", "DIU": 1525, "country": "CN"},
{"date":"2018-08-02", "DIU": 1525, "country": "CN"}
];
// 时间字符串 转换为时间戳
// var str = "2018-08-01";
// console.log(Date.parse(str));
var arr = arr3.sort(function(a, b){
if(a.date == b.date){
return b.DIU - a.DIU;
}
return Date.parse(b.date) - Date.parse(a.date);
})
console.log(arr);
// 中文('zh') 文字的拼音的首字母 姓名 如何排序
var arr2 = [
{ name: '武丽昕', num: 78 },
{ name: '汤文博', num: 38 },
{ name: '卢文博', num: 58 },
{ name: '邓钧键', num: 97 },
{ name: '刘继昂', num: 56 },
{ name: '栗军安', num: 78 },
{ name: '屈晓月', num: 98 },
{ name: '付秋萍', num: 79 }
];
var arr4 = arr2.sort(function(a, b){
return a.name.localeCompare(b.name, 'zh');
})
console.log(arr4);
</script>
数组去重
时间复杂度去重
<script>
// 时间复杂度 二重循环 那么时间上就用的比较多一点点 用时间换空间
var arr = [1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9];
function removal(arr){
for(var i = 0; i < arr.length; i++){
for(var j = i + 1; j < arr.length; j++){
if(arr[i] == arr[j]){
arr.splice(j,1);
j--;//重置下标 下次比较 对补位到该下标的值进行判断
}
}
}
return arr;
}
/*
1st 0 1 1 1 相等 将第1个的1 给删除 然后 下标为2的1 补位到了下标为1的位置上
2nd 0 1 j++ j 2 这时 1 和第2个位置上的2来比较,漏掉了 补位到下标1上这个1
*/
console.log(removal(arr));
</script>
空间复杂度去重
<script>
// 空间复杂度 减少循环 用单循环 但是 需要建立 一个空对象 一个空数组 这样导致 内存空间占用多一点点 用空间换时间
var arr = [1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9];
function removal2(arr){
var nArr = [];//用来存储去重的数据 得到去重后的数组
var json = {};//对象 用来记录已经放入到nArr中的值
for(var i = 0; i < arr.length; i++){
if(!json[arr[i]]){
nArr.push(arr[i]);
json[arr[i]] = true;
}
}
console.log(json);
return nArr;
}
/*
var obj = {
name:'joth';
}
var aa = 'name';
obj[aa] <==> obj.name
json[arr[0]] <==> json['1'] <==> json.1
1 nArr = [] json = {} i = 0 json['1']--false nArr = [1] json = {'1' : true}
2 nArr = [1] json = {'1': true} i = 1; json['1']--true 不执行了
3 nArr = [1] json = {'1': true} i = 2; json['1']--true 不执行了
4 nArr = [1] json = {'1': true} i = 3; json['2']--false nArr = [1,2] json = {'1':true,'2': true}
5
*/
console.log(removal2(arr));
</script>
数组的其他方法
<script>
var arr = ['a','b','c','d','e','f','g','h'];
// join
// var str = arr.join('-');
// console.log(str);'a-b-c-d-e'
// concat();
// arr2 = arr.concat('哈哈',[1,2,3]);
// console.log(arr2);
// reverse
// console.log(arr.reverse());
// indexOf()
console.log(arr.indexOf('c'));//2
console.log(arr.indexOf('c',4));//-1
// slice() 用法和字符串slice方法 相同
console.log(arr.slice(1,4));
console.log(arr.slice(3,-2));
// Array.isArray(arr);// 判断对象是否为数组
var obj = {};
console.log(typeof arr);//'object'
console.log(typeof obj);//'object'
console.log(Array.isArray(arr));//true
console.log(Array.isArray(obj));//false
</script>
数组的其他迭代方法
<script>
var arr = [1,2,3,4,5,6,7,8];
var arr2 = [1,3,5,7,9];
// every
var aa = arr.every(function(v,i){
return v < 10;
})
console.log(aa);//true
// some
var bb = arr.some(function(v,i){
return v % 2 == 0;
})
console.log(bb);//true
// filter
var nArr = arr.filter(function(v,i){
return v % 2 == 0;
})
console.log(nArr);//[2,4,6,8]
// map
var arr3 = arr.map(function(val,i){
return val * val
})
console.log(arr3);
// for(var i = 0; i < arr.length; i++){
// console.log(arr[i]);
// }
//forEach 相当于数组专用的for循环
arr.forEach(function(v,i){
console.log(i, v);
})
</script>
DOM—Document Object Model 文档对象模型
获取子节点
父节点.childNodes;获取父元素下的所有节点
父节点.children; 获取父元素下的所有子元素节点
<script>
window.onload = function(){
var oUl = document.getElementsByTagName('ul')[0];
// console.log(oUl.children.length);//4
console.log(oUl.childNodes.length);// ie 4 chrome 9
// nodeType 节点类型 nodeName 节点名称 nodeValue
console.log(oUl.childNodes[0].nodeType);//3
console.log(oUl.childNodes[1].nodeType);//1
console.log(oUl.childNodes[2].nodeType);//3
console.log(oUl.childNodes[3].nodeType);//1
console.log(oUl.childNodes[0].nodeName);//#text 文本节点
console.log(oUl.childNodes[1].nodeName);//LI li元素节点
console.log(oUl.childNodes[0].nodeValue);//hahaha
console.log(oUl.childNodes[1].nodeValue);//null
var aLi = [];
for(var i = 0; i < oUl.childNodes.length; i++){
if(oUl.childNodes[i].nodeType == 1){
aLi.push(oUl.childNodes[i]);
}
}
console.log(aLi);
console.log(oUl.children)
}
</script>
获取父节点
子元素.parentNode:获取父元素
子元素.offsetParent:获取距离子元素最近的有定位属性的父元素,如果所有的父元素都没有定位属性,则获取body
<script>
window.onload = function(){
var oDiv4 = document.getElementById('div4');
console.log(oDiv4.parentNode.id);//'div3'
console.log(oDiv4.offsetParent);//
}
</script>
<script>
window.onload = function(){
var oDiv4 = document.getElementById('div4');
// oDiv4 距离 body的top值是多少
// 获取元素和定位父级直接的定位top值 offsetTop
// console.log(oDiv4.offsetTop);
function getTop(el){
var iTop = 0;
while(el.offsetParent){
iTop += el.offsetTop;
el = el.offsetParent;
}
return iTop;
}
/*
1 oDiv4 while(oDiv4.offsetParent) while(oDiv3) iTop += 20 el = oDiv3
2 oDiv3 while(oDiv3.offsetParent) while(oDiv1) iTop += 50 el = oDiv1
3 oDiv1 while(oDiv1.offsetParent) while(body) iTop += 100 el = body
4 body while(body.offsetParent) while(null); exit
*/
console.log(getTop(oDiv4));
}
</script>
获取其他节点(都有兼容性)
firstChild 和 firstElementChild 获取父元素下的第一个子节点
lastChild 和 lastElementChild 获取父元素下的最后一个子元素(兼容性同上)
nextSibling 和 nextElementSibling 获取当前元素的下一个兄弟节点(兼容性同上)
previousSibling 和previousElementSibling 获取当前元素的上一个兄弟节点(兼容性同上)
<script>
window.onload = function(){
var oUl = document.getElementsByTagName('ul')[0];
console.log(oUl.firstChild);//chrome ff 标准浏览器 文本节点 ie 8- 元素节点
console.log(oUl.firstElementChild);//chrome ff 第一个元素子节点 ie下undefind
// function getFchild(el){
// if(el.firstElementChild){
// return el.firstElementChild;
// }else{
// return el.firstChild;
// }
// }
var fChild = oUl.firstElementChild || oUl.firstChild;
// 短路或 当第一项为真 则返回第一项 第一项为假 则返回第二项
// 在chrome中 第一项为 真 返回第一项 而在ie中 第一项得到的值 undefined 为假 所以会返回 firstChild
var lChild = oUl.lastElementChild || oUl.lastChild;
lChild.style.background = 'red';
var oLi = document.getElementById('li1');
var nSb = oLi.nextElementSibling || oLi.nextSibling;
nSb.style.background = 'green';
var pSb = oLi.previousElementSibling || oLi.previousSibling;
pSb.style.background = 'pink';
}
</script>
操作节点
创建节点:
添加节点:在父元素的最后追加节点 appendChild(节点/元素)
插入节点:在父节点中 的某个子节点之前插入一个新节点 父节点.insertBefore(要插入的节点,目标节点) 在目标节点之前插入
删除节点:
替换节点:父节点.replaceChild(新节点,要被替换的节点)
克隆节点:cloneNode(布尔值) 复制一个节点 将复制的节点返回,参数默认为false 则不克隆节点内的内容,返回空节点。 当参数为true 则将节点及节点内容全部复制
<script>
window.onload = function(){
var oUl = document.getElementById('list');
// oUl.innerHTMl += '- 中秋节
';
// 创建一个li
var oLi = document.createElement('li');
var txt = document.createTextNode('中秋节');
// 将创建文本节点追加到创建的元素节点
oLi.appendChild(txt);
//将创建的元素节点 追加到父节点
oUl.appendChild(oLi);
// 插入节点
var oLi = document.createElement('li');
oLi.innerHTML = '情人节';
oUl.insertBefore(oLi,oUl.children[1]);
// 删除节点
// 从父节点中 删除一个子节点
// oUl.removeChild(oUl.children[3]);
oUl.children[3].remove();// 删除本身
// 替换元素
var oLi = document.createElement('li');
oLi.innerHTML = '乞巧节';
oUl.replaceChild(oLi,oUl.children[4]);
// 克隆
var cLi = oUl.children[0].cloneNode(true);
console.log(cLi);
oUl.appendChild(cLi);
}
获取标签的方法和设置/获取属性的新方法
之前的获取标签的方法
新的方法 ie9+
<script>
window.onload = function(){
// getElementById('box');
// var oBox = document.querySelector('#box');
// console.log(oBox);
// var oDiv = document.querySelector('div');//获取div中的第0个
// console.log(oDiv);
var aDiv = document.querySelectorAll('div');
console.log(aDiv);
var aDiv1 = document.querySelectorAll('.div1');
console.log(aDiv1);
}
</script>
设置和获取属性值的新方法
<script>
window.onload = function(){
var oA = document.querySelector('#box');
console.log(oA.title);
oA.title = 'abc1';
console.log(oA.index);
console.log(oA.getAttribute('index'));
console.log(oA.getAttribute('target'));
oA.setAttribute('index','888');
}
</script>
表格的操作
表格操作API 表头 oTab.tHead 表尾 oTab.tFoot 表体 oTab.tBodies[下标]
rows 获取行 cells 获取单元格
<script>
window.onload = function(){
var oTab = document.getElementById('tab');
console.log(oTab.tHead);
console.log(oTab.tFoot);
console.log(oTab.tBodies[0]);
// 行
console.log(oTab.tBodies[0].rows[0]);
// 单元格
console.log(oTab.tBodies[0].rows[0].cells[1].innerHTML);
}
</script>
Browser Object Model 浏览器对象模型—和浏览器相关的一些API,BOM 的核心是 window
系统弹窗
alert(‘内容’)警告弹窗
confirm(‘内容’)带有确定的弹窗,返回值 点确定返回 true 取消返回false
prompt(‘标题’,‘默认内容’)可以输入内容的弹窗,当点击确定时 有内容就返回内容没有填写内容就返回空 点取消返回null
<script>
// alert('123123');
// 带有确认和取消的弹窗
// var isOk = confirm('are you ok?');
// console.log(isOk);
var str = prompt('请开始你的表演','才艺名称');
console.log(str);
</script>
open()和close();
open
close
<script>
window.onload = function(){
var oBtn = document.getElementsByTagName('button');
oBtn[0].onclick = function(){
open('aaa.html','_blank');
}
}
</script>
<script>
window.onload = function(){
document.getElementsByTagName('button')[0].onclick = function(){
close();
}
}
</script>
location 窗口加载信息
console.log(location.hash);//哈希值
console.log(location.host);//域名+端口
console.log(location.hostname);//主域名
console.log(location.href);//路径地址
console.log(location.origin);//来源
console.log(location.protocol);//协议
console.log(location.port);//端口
console.log(location.search);//传参
其他功能
document.getElementsByTagName('button')[0].onclick = function(){
window.location.reload();//刷新页面
}
document.getElementsByTagName('button')[1].onclick = function(){
window.location = 'http://www.163.com';// 跳转页面
}
history 历史记录
navigator 导航 反馈浏览器和操作系统的信息
<script>
window.onload = function(){
var oDiv = document.getElementsByTagName('div')[0];
oDiv.innerHTML = '浏览器代号:' + navigator.appCodeName + '
' +
'浏览器名称:' + navigator.appName + '
' +
'浏览器版本:' + navigator.appVersion + '
' +
'是否启用cookie:' + navigator.cookieEnabled + '
' +
'浏览器代理:' + navigator.userAgent + '
' +
'浏览器语言:' + navigator.language + '
' +
'浏览器语言:' + navigator.systemLanguage + '
' +
'当前系统:' + navigator.platform + '
'
}
</script>
body 位置属性
client系列宽度获取
<script>
window.onload = function(){
var oBox = document.getElementById('box');
var oDiv = document.getElementById('div1');
// 元素的可视宽
console.log(oBox.clientWidth);//100
console.log(oDiv.clientWidth);//240 width + 左右padding
// 浏览器可视区的宽高
console.log(document.documentElement.clientHeight);
console.log(document.documentElement.clientWidth);
// 上边框和左边框
console.log(oDiv.clientTop);//5
console.log(oDiv.clientLeft);//5
}
</script>
offset系列
<script>
window.onload = function(){
var oDiv = document.getElementsByTagName('div')[0];
console.log(oDiv.offsetTop);//100
console.log(oDiv.offsetLeft);//50
console.log(oDiv.offsetWidth);//130
console.log(oDiv.offsetHeight);//130
}
</script>
scrollTop系列
<script>
window.onload = function(){
window.onscroll = function(){
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
console.log(scrollTop);
}
}
</script>
//元素的滚动
<script>
window.onload = function(){
var oBox = document.getElementById('box');
// 所有的或 卷走宽高和实际内容的宽高 都写父盒子
oBox.onscroll = function(){
console.log(oBox.scrollTop);
console.log(oBox.scrollHeight);//1002 1000+2border
}
}
</script>
懒加载
当窗口尺寸发生变化的事件 onresize
事件对象
当事件触发时,关于触发事件的对象(鼠标,键盘按键)的一些具体的属性,例如当点击事件发生时 鼠标在可视区的点击位置,在元素中的点击位置,点击的目标是谁等
事件对象是window的一个属性,window.event window可以被省略
在ie chrome中 可以使用event 但是在ff中 要使用事件对象 需要进行传参 ev来使用事件对象
<script>
window.onload = function(){
var oDiv = document.getElementById('box');
oDiv.onclick = function(ev){
// console.log(event.target);//目标 当前触发事件的对象 (谁被点击了)
// console.log(event.type);// 触发了什么事件
// console.log(event.pageX);// 鼠标点击相对于整个文档的left值
// console.log(event.pageY);// 鼠标点击相对于整个文档的top值
// console.log(event.clientX);// 鼠标点击相对于浏览器可视区的left值
// console.log(event.clientY);// 鼠标点击相对于浏览器可视区的top值
// console.log(event.offsetX);// 鼠标点击相对于元素的left值
// console.log(event.offsetY);// 鼠标点击相对于元素的top值
// event ie 和 chrome 可以使用 ff 不能使用
// ff 进行事件函数的传参 传ev ff下要使用传参进来的ev
var ev = ev || event;//事件对象的兼容
// console.log(ev);
// console.log(ev.target);//chrome ff
// console.log(ev.srcElement);//ie
var target = ev.target || ev.srcElement;
console.log(target);
}
}
</script>
事件的绑定与取消
后写的按钮的点击事件函数会覆盖先写的
给同一个按钮的同一个事件上绑定多个事件处理函数
chrome ff 下事件绑定 addEventListener(‘事件’,事件处理函数,布尔值?(setCapture)是否捕获)----使用事件时 不带 on onclick --》 click setCapture 默认为false (冒泡事件流) 如果为true 就使用 捕获事件流
ie attachEvent(‘事件’,事件处理函数)
<script>
window.onload = function(){
var oBtn = document.getElementById('btn');
// oBtn.onclick = function(){
// console.log(1);
// }
// oBtn.onclick = function(){
// console.log(222222);
// }
// 后写的按钮的点击事件函数会覆盖先写的
// 给同一个按钮的同一个事件上绑定多个事件处理函数
// oBtn.addEventListener('click',function(){
// },false);
function fn1(){
console.log(1);
}
function fn2(){
console.log(22222);
}
// oBtn.addEventListener('click',fn1,false);//给按钮的点击事件 绑定第一个函数
// oBtn.addEventListener('click',fn2,false);//给按钮的点击事件 绑定第二个函数
// ie中的事件绑定
// oBtn.attachEvent('onclick',fn1);
// oBtn.attachEvent('onclick',fn2);
if(oBtn.addEventListener){//元素对象可以使用该方法 就为真 不能使用就为假
oBtn.addEventListener('click',fn1,false);
oBtn.addEventListener('click',fn2,false);
}else{
oBtn.attachEvent('onclick',fn1);
oBtn.attachEvent('onclick',fn2);
}
}
</script>
//事件绑定的函数封装
function bindEvent(el,oEvent,fn){
if(el.addEventListener){
el.addEventListener(oEvent, fn, false);
}else{
el.attachEvent('on' + oEvent, fn);
}
}
事件取消绑定
<script>
window.onload = function(){
var oBtn = document.getElementsByTagName('button');
function fn1(){
console.log('我有点击事件了')
}
// oBtn[1].onclick = function(){
// oBtn[0].addEventListener('click',fn1,false);
// }
// oBtn[2].ondblclick = function(){
// oBtn[0].removeEventListener('click',fn1);
// }
// oBtn[1].onclick = function(){
// oBtn[0].attachEvent('onclick',fn1);
// }
// oBtn[2].ondblclick = function(){
// oBtn[0].detachEvent('onclick',fn1);
// }
// 事件绑定函数
function bindEvent(el,oEvent,fn){
if(el.addEventListener){
el.addEventListener(oEvent, fn, false);
}else{
el.attachEvent('on' + oEvent, fn);
}
}
// 取消绑定函数
function removeEvent(el, oEvent, fn){
if(el.removeEventListener){
el.removeEventListener(oEvent,fn);
}else{
el.detachEvent('on' + oEvent,fn);
}
}
oBtn[1].onclick = function(){
bindEvent(oBtn[0],'click', fn1);
}
oBtn[2].ondblclick = function(){
removeEvent(oBtn[0], 'click', fn1);
}
}
</script>
DOM事件流
事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所经过的所有节点都会收到该事件,这个传播过程即 DOM 事件流。(如:当你点击了一个元素时,该事件不会只在该元素上触发,而会通过某种顺序,在DOM树中进行传播,如果传播到的节点有该事件的处理函数,则该函数被触发)
DOM事件流 分为三个阶段
//冒泡事件流
<script>
window.onload = function(){
var oDiv1 = document.getElementById('div1');
var oDiv2 = document.getElementById('div2');
var oDiv3 = document.getElementById('div3');
oDiv3.onclick = function(){
console.log('div3');
}
oDiv1.onclick = function(){
console.log('div1');
}
document.body.onclick = function(){
console.log('body');
}
document.onclick = function(){
console.log('document');
}
//div3-->div1-->body-->document
}
</script>
//捕获事件流
<script>
window.onload = function(){
var oDiv1 = document.getElementById('div1');
var oDiv2 = document.getElementById('div2');
var oDiv3 = document.getElementById('div3');
oDiv3.addEventListener('click',function(){
console.log('div3')
},true)
oDiv1.addEventListener('click',function(){
console.log('div1');
},true)
document.addEventListener('click',function(){
console.log('document');
},true)
// document-->div1-->div3
}
</script>
取消冒泡
<script>
window.onload = function(){
var oDiv1 = document.getElementById('div1');
var oDiv2 = document.getElementById('div2');
var oDiv3 = document.getElementById('div3');
oDiv3.onclick = function(ev){
var ev =ev || event;
console.log('div3');
ev.stopPropagation ? ev.stopPropagation() : ev.cancelBubble = true;
}
oDiv1.onclick = function(){
console.log('div1');
}
document.body.onclick = function(){
console.log('body');
}
document.onclick = function(){
console.log('document');
}
}
</script>
事件的默认行为
当事件触发时,本身默认就能执行某些操作,就称之为事件的默认行为。
取消事件默认行为
<script>
window.onload = function(){
// 事件驱动方式
// document.oncontextmenu = function(){
// console.log(1);
// return false;
// }
// addEventListener 绑定
// document.addEventListener('contextmenu',function(ev){
// var ev = ev || event;
// console.log(11);
// // return false;
// ev.preventDefault();
// },false)
// ie 事件绑定 attachEvent
document.attachEvent('oncontextmenu',function(ev){
var ev = ev || event;
console.log('ie');
ev.returnValue = false;
})
}
</script>
键盘事件
键盘事件:onkeydown按键按下 onkeyup按键抬起
键盘按键确定: ev.keyCode ===> 按键值
专门的三个方法来进行 组合键的使用
<script>
window.onload = function(){
var oIn = document.getElementById('txt');
var oDiv = document.getElementsByTagName('div')[0];
document.onkeydown = function(ev){
var ev = ev || evnet;
// 根据键值 来判断按下了哪个键
// 希望ctrl+enter来发送
// if(ev.keyCode == 13 && ev.keyCode == 17){
// oDiv.innerHTML = oIn.value;
// }
// 专门的三个方法来进行 组合键的使用
if(ev.keyCode == 13 && ev.ctrlKey){
oDiv.innerHTML = oIn.value;
}
}
}
</script>
上下左右按键控制div的移动完美版
<script>
window.onload = function(){
var oDiv = document.getElementById('box');
var il,ir,id,iu;
setInterval(function(){
if(il) oDiv.style.left = oDiv.offsetLeft - 10 + 'px';
if(iu) oDiv.style.top = oDiv.offsetTop - 10 + 'px';
if(ir) oDiv.style.left = oDiv.offsetLeft + 10 + 'px';
if(id) oDiv.style.top = oDiv.offsetTop + 10 + 'px';
},20)
document.onkeydown = function(ev){
var ev = ev || evnet;
switch(ev.keyCode){
case 37:// 左
il = true;
break;
case 38:// 上
iu = true;
break;
case 39:// 右
ir = true;
break;
case 40:// 下
id = true;
break;
}
}
document.onkeyup = function(ev){
var ev = ev || event;
switch(ev.keyCode){
case 37:// 左
il = false;
break;
case 38:// 上
iu = false;
break;
case 39:// 右
ir = false;
break;
case 40:// 下
id = false;
break;
}
}
}
</script>
滚轮事件
<script>
window.onmousewheel = document.onmousewheel = function(ev){
var ev = ev || event;
console.log(ev.wheelDelta);//下 -120 上 120
}
document.addEventListener('DOMMouseScroll',function(ev){
console.log(ev.detail);//下3 上 -3
})
</script>
//兼容
<script>
function bindEvent(el, oEvent, fn){
if(el.addEventListener){
el.addEventListener(oEvent, fn, false);
}else{
el.attachEvent('on' + oEvent, fn);
}
}
function iScroll(ev){
var ev = ev || event;
var bDown = false;// 当bDown无论在任何浏览器 只要它的值为真就说明滚轮在向下滚动 为假则滚轮在向上滚动
// if(ev.wheelDelta){//wheelDelta能否使用 如果支持该属性就说明 chrome ie 那么就使用该属性
// if(ev.wheelDelta < 0) bDown = true;//如果当前的wheelDelta 取值小于0 那么说明滚轮是在chrome向下滚动 将bDown赋值为 true
// }else{
// // 否则 不能使用wheelDelta 说明是ff浏览器 使用ev.detail
// if(ev.detail > 0) bDown = true;//如果当时使用ev.detail 取值大于0 那么说明滚轮是在火狐浏览器中向下滚动 将bDown赋值为 true
// }
// 三目写法
bDown = ev.wheelDelta ? ev.wheelDelta < 0 : ev.detail > 0;
if(bDown){
console.log('我向下滚');
}else{
console.log('我向上滚');
}
}
bindEvent(document, 'mousewheel', iScroll);// chrome ie
bindEvent(document, 'DOMMouseScroll', iScroll);// ff
</script>
事件委托
将事件添加到父元素上,当事件发生时,父元素会找到对应触发事件的子元素去处理,后期添加的子元素,依然有这个事件。
<script>
window.onload = function(){
var oUl = document.getElementsByTagName('ul')[0];
// var aLi = oUl.getElementsByTagName('li');
var oBtn = document.getElementsByTagName('button')[0];
// for(var i = 0; i < aLi.length; i++){
// aLi[i].onclick = function(){
// console.log(this.innerHTML)
// }
// }
// oBtn.onclick = function(){
// var oLi = document.createElement('li');
// oLi.innerHTML = 'new';
// oUl.appendChild(oLi);
// for(var i = 0; i < aLi.length; i++){
// aLi[i].onclick = function(){
// console.log(this.innerHTML)
// }
// }
// }
// 事件委托
oUl.onclick = function(ev){
var ev = ev || event;
// 寻找到点了那个子元素li 触发事件的对象
// console.log(ev.target);
var target = ev.target || ev.srcElement;//找到真正触发事件的子元素 兼容
console.log(target.innerHTML);
}
oBtn.onclick = function(){
var oLi = document.createElement('li');
oLi.innerHTML = 'new';
oUl.appendChild(oLi);
}
}
</script>
拖拽效果:
鼠标在元素上按下:onmousedown 需要计算一个按下的位置记录(鼠标点击的位置和元素定位的左上角的差值)
鼠标按下的同时 进行鼠标移动:onmousemove
最后鼠标抬起:onmouseup
鼠标移动和释放要写给document
文字被选中:在mousedown的最后取消默认事件 return false ie:setCapture 设置事件捕获releaseCapture 释放事件捕获
<script>
window.onload = function(){
var oDiv = document.getElementById('box');
var disX = 0;
var disY = 0;
// 鼠标按下
oDiv.onmousedown = function(ev){
var ev = ev || event;
disX = ev.clientX - oDiv.offsetLeft;
disY = ev.clientY - oDiv.offsetTop;
// 鼠标开始移动 将鼠标的位置 赋值给div的left和top 使div跟着移动
document.onmousemove = function(ev){
var ev = ev || event;
oDiv.style.top = ev.clientY - disY + 'px';
oDiv.style.left = ev.clientX - disX + 'px';
}
document.onmouseup = function(){
if(oDiv.releaseCapture) oDiv.releaseCapture();
document.onmousemove = null;
document.onmouseup = null;
}
if(this.setCapture) this.setCapture();
return false;
}
}
</script>
拖拽区域限定
<script>
window.onload = function(){
var oDiv = document.getElementById('box');
var disX = 0;
var disY = 0;
// 鼠标按下
oDiv.onmousedown = function(ev){
var ev = ev || event;
disX = ev.clientX - oDiv.offsetLeft;
disY = ev.clientY - oDiv.offsetTop;
// 鼠标开始移动 将鼠标的位置 赋值给div的left和top 使div跟着移动
document.onmousemove = function(ev){
var ev = ev || event;
var t = ev.clientY - disY;
var l = ev.clientX - disX;
// 判断t 和 l 不能超过 可视区的宽/高- 该元素的宽/高
// 0 就限制范围 50 类似吸附效果
if(t <= 50){
t = 0;
}else if(t >= document.documentElement.clientHeight - oDiv.offsetHeight - 50){
t = document.documentElement.clientHeight - oDiv.offsetHeight;
}
if(l <= 50){
l = 0;
}else if(l >= document.documentElement.clientWidth - oDiv.offsetWidth - 50){
l = document.documentElement.clientWidth - oDiv.offsetWidth;
}
oDiv.style.top = t + 'px';
oDiv.style.left = l + 'px';
}
document.onmouseup = function(){
document.onmousemove = null;
document.onmouseup = null;
}
return false;
}
}
</script>
碰撞检测
if(oDiv.offsetLeft + oDiv.offsetWidth > oBigBox.offsetLeft && oDiv.offsetLeft < oBigBox.offsetLeft + oBigBox.offsetWidth && oDiv.offsetTop + oDiv.offsetHeight > oBigBox.offsetTop && oDiv.offsetTop < oBigBox.offsetTop + oBigBox.offsetHeight){
oBigBox.style.background = 'green';
}else{
oBigBox.style.background = '';
}
缓冲运动框架
回顾匀速运动框架:特点 步长是固定
缓冲运动:步长(速度 ) 通过公式来进行计算 (目标值 - 当前值)/ 运动系数(6–10) 运动系数越小 速度就越快
运动到最后时 速度不够 1 那么我们需要将小数取得1 向上取整
<script>
function getStyle(el, attr){
return el.currentStyle ? el.currentStyle[attr] : getComputedStyle(el, false)[attr];
}
window.onload = function(){
var oDiv = document.getElementById('box');
var oBtn = document.getElementsByTagName('button')[0];
var timer = null;
oBtn.onclick = function(){
clearInterval(timer);
timer = setInterval(function(){
var cur = parseInt(getStyle(oDiv, 'left'));
var speed = (800 - cur) / 10;
speed = Math.ceil(speed);
if( cur == 800){
clearInterval(timer);
}
oDiv.style.left = cur + speed + 'px';
},20)
}
}
</script>
缓冲来回运动封装
<script>
function getStyle(el, attr){
return el.currentStyle ? el.currentStyle[attr] : getComputedStyle(el, false)[attr];
}
window.onload = function(){
var oDiv = document.getElementById('box');
var aBtn = document.getElementsByTagName('button');
// var timer = null;
aBtn[0].onclick = function(){
bufferMove(oDiv, 'left', 50);
}
aBtn[1].onclick = function(){
bufferMove(oDiv, 'left', 1200);
}
function bufferMove(el, attr, target){
clearInterval(timer);//防止多次点击 定时器累加
timer = setInterval(function(){
var cur = parseInt(getStyle(el, attr)); //每次定时器执行 获取元素的当前属性的值 转换为数字
var speed = (target - cur)/10; //通过公式计算速度
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(cur == target){
clearInterval(timer);
}
el.style[attr] = cur + speed + 'px';
},20)
}
}
</script>
多物体缓冲运动
function bufferMove(el, attr, target){
clearInterval(el.timer);//防止多次点击 定时器累加
el.timer = setInterval(function(){
var cur = parseInt(getStyle(el, attr)); //每次定时器执行 获取元素的当前属性的值 转换为数字
var speed = (target - cur)/10; //通过公式计算速度
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(cur == target){
clearInterval(el.timer);
}
el.style[attr] = cur + speed + 'px';
},20)
}
function getStyle(el, attr){
return el.currentStyle ? el.currentStyle[attr] : getComputedStyle(el, false)[attr];
}
使用多种属性(left,top,width,height,opacity)
function bufferMove(el, attr, target){
clearInterval(el.timer);//防止多次点击 定时器累加
el.timer = setInterval(function(){
if(attr == 'opacity'){
var cur = parseInt(getStyle(el, attr) * 100);//如果是透明度 则乘以100 从小数转换为整数方便后续计算
}else{
var cur = parseInt(getStyle(el, attr));//其他属性
}
var speed = (target - cur) / 10;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(target == cur){
clearInterval(el.timer);
}
if(attr == 'opacity'){
el.style.opacity = (cur + speed) / 100;
el.style.filter = 'alpha(opacity=' + (cur + speed) + ')';
}else{
el.style[attr] = cur + speed + 'px';
}
},20)
}
function getStyle(el, attr){
return el.currentStyle ? el.currentStyle[attr] : getComputedStyle(el, false)[attr];
}
多属性同时运动
function bufferMove(el, json){
clearInterval(el.timer);//防止多次点击 定时器累加
el.timer = setInterval(function(){
var flag = true;
for(var attr in json){
if(attr == 'opacity'){
var cur = parseInt(getStyle(el, attr) * 100);//如果是透明度 则乘以100 从小数转换为整数方便后续计算
}else{
var cur = parseInt(getStyle(el, attr));//其他属性
}
var speed = (json[attr] - cur) / 10;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(json[attr] != cur){
flag = false;
}
if(attr == 'opacity'){
el.style.opacity = (cur + speed) / 100;
el.style.filter = 'alpha(opacity=' + (cur + speed) + ')';
}else{
el.style[attr] = cur + speed + 'px';
}
}
if(flag){
clearInterval(el.timer);
}
},20)
}
function getStyle(el, attr){
return el.currentStyle ? el.currentStyle[attr] : getComputedStyle(el, false)[attr];
}
链式运动
function bufferMove(el, json, fn){
clearInterval(el.timer);//防止多次点击 定时器累加
el.timer = setInterval(function(){
var flag = true;
for(var attr in json){
if(attr == 'opacity'){
var cur = parseInt(getStyle(el, attr) * 100);//如果是透明度 则乘以100 从小数转换为整数方便后续计算
}else{
var cur = parseInt(getStyle(el, attr));//其他属性
}
var speed = (json[attr] - cur) / 10;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(json[attr] != cur){
flag = false;
}
if(attr == 'opacity'){
el.style.opacity = (cur + speed) / 100;
el.style.filter = 'alpha(opacity=' + (cur + speed) + ')';
}else{
el.style[attr] = cur + speed + 'px';
}
}
if(flag){
clearInterval(el.timer);
if(fn) fn.call(el); //强制将函数的this对象指向参数对象
// 我要喊这个el元素来执行这个函数,这样这个函数就被这个el元素调用了 这时这个函数中的this就指向了el
}
},20)
}
面向对象的编程 不是一个程序,是一个编程的思维。
创建对象的方式
实例化对象 var obj = new Object();
字面量创建 var obj = {}
工厂模式创建对象
<script>
function createPerson(name, age, sex){
// 先创建一个空对象 原料
var obj = {};
// 给空对象创建属性,然后将形参获取的值 赋值给该属性 加工
obj.name = name;
obj.age = age;
obj.sex = sex;
// 将创建的对象返回 出厂
return obj;
}
var person1 = createPerson('joth', 18, 'male');
var person2 = createPerson('rose', 22, 'female');
var person3 = createPerson('tom', 34, 'male');
console.log(person1,person2,person3);
//在面向对象中---创建的对象 都应该有一个共同的类 如每个人 应该属于 人类
// instanceof 判断对象是够属于某个类
console.log(person1 instanceof createPerson);//false
// 我们虽然可以通过createPerson函数来批量创建人,但是我们缺少了一个人类 的类
// 理论上 我们需要人 --》隶属于 人类
console.log(person1 instanceof Object);//true
// 所有js中万物皆对象 所有对象 都有一个自己的类 然后这些个类 又都属于 Object类
var arr = [];
var str = new String('aaa');
console.log(arr instanceof Array);// arr属于数组类
console.log(str instanceof String);//str属于字符串类
console.log(arr instanceof Object);
console.log(str instanceof Object);
// arr-->属于Array类---> 属于Object类
</script>
构造函数创建(constructor)
面向对象中 理论是应该由类来创建隶属于类的对象,但是js中没有类,所以我们使用构造函数来模拟类,即便到了es6中,有了Class关键字来创建类,这个类依然是由构造函数模拟的
构造函数的命名 首字母就大写
构造函数中不再创建空对象 也不在返回该对象 所有的属性都写给this 在定义构造函数时this对象是为空
当你创建对象是 对象构造函数使用操作符 new 就可以进行对象的创建
new操作符的主要作用:
1.隐式创建了一个空对象
2.空对象的__proto__指向构造函数的原型prototype
3.this指向了这个空对象,添加属性和方法
4.隐式的返回该空对象
<script>
// 构造函数Person(类) 首字母大写就是为了和一般函数做个区别 约定俗成首字母大写的都是构造函数
function Person(name, age, sex){
// var obj = {};
// 属性
this.name = name;
this.age = age;
this.sex = sex;
// 方法(函数)
this.eat = function(){
console.log('吃饭饭');
}
// return obj;
}
var person1 = new Person('joth', 18, 'male');
var person2 = new Person('rose', 22, 'female');
console.log(person1);
console.log(person1 instanceof Person);//true 某个人 属于 人类
person1.eat();
person2.eat();
console.log(person1.eat == person2.eat);//false;
// 两个对象中的方法不相等---》 函数本事对象 栈区存的是地址 两个函数的地址是不同的 所以不相等
// 这个两个函数的功能一样的 如果现在创建100 人 那么就有这样功能相同的的函数100个 浪费了内存空间
// 希望所有对象 都共用1个这样的函数
// 原型 prototype
</script>
原型和原型创建对象
<script>
//构造函数
function Person(){}
// 原型对象上添加属性和方法 原型创建对象
Person.prototype.name = 'joth';
Person.prototype.age = 22;
Person.prototype.sex = 'male';
Person.prototype.eat = function(){
console.log('吃饭饭');
}
// 实例化对象
var person1 = new Person();
var person2 = new Person('rose', 22, 'female');
console.log(person1.eat == person2.eat);//true 说明是使用了同一个地址指向的函数 说明该函数共用
console.log(person1.name,person2.name);
// 由于共用 所以 所有对象的属性都相同
console.log(Person.prototype);
console.log(Person.prototype.constructor);
</script>
混合创建
<script>
// 混合创建
// 将值需要变化的属性和方法写在构造函数中
function Person(name, age, sex){
this.name = name;
this.age = age;
this.sex = sex;
}
// 将所有对象共用的属性和方法写在构造函数的原型对象上
Person.prototype.eat = function(){
console.log(this.name + '吃饭饭');
}
var person1 = new Person('joth', 18, 'male');
var person2 = new Person('王凯辉', 22, 'male');
console.log(person1.name, person2.name);
person1.eat();
person2.eat();
console.log(person1 instanceof Person);//true
console.log(person2 instanceof Person);//true
console.log(person1.eat == person2.eat);//true
</script>
通过面向对象的方法来编写程序
面向对象程序初学三部曲:
面向对象改写选项卡
动态混合创建对象
首先判断构造函数中是否有该方法(函数) 没有 再向原型对象中添加
<script>
// function Person(name){
// this.name = name;
// this.eat = function(){
// console.log('吃肉肉');
// }
// }
// Person.prototype.eat = function(){
// console.log('吃饭饭');
// }
// var person1 = new Person('joth');
// person1.eat();
// console.log(person1);
// 在构造函数下和原型上都有该该方法,当调用时 执行构造函数下的方法 原型上的该方法就是冗余
// 动态创建对象(使用比较少)
function Person(name){
this.name = name;
this.eat = function(){
console.log('吃肉肉');
}
// 判断有没有eat方法(方法就是函数)有就不在原型上添加 没有 就在原型上添加
if(typeof this.eat != 'function'){
Person.prototype.eat = function(){
console.log('吃饭饭');
}
}
}
var person1 = new Person('joth');
person1.eat();
console.log(person1);
</script>
命名空间
call与apply的使用
call和apply的作用是:改变函数中的this指向。
<script>
function fn(a, b){
console.log(this, a + b);
}
fn(1,2);// window 3
var obj = {
m: 10,
n: 22
}
// fn.call(obj, obj.m, obj.n);// obj 32
fn.apply(obj,[obj.m, obj.n]);//obj 32
</script>
面向对象的继承
原型链继承
原型链:在多个构造函数的原型中 原型的__ptoto__属性链接到另一个构造函数的原型就称之为原型链 如:
原型链继承,就是将子类的原型上的__proto__属性指向父类的一个实例化对象,从而将父类的构造函数中的属性和方法和父类原型上的属性和方法全部继承给子类的原型
<script>
// 父类 父构造函数
function Person(name, age, sex){
this.name = name;
this.age = age;
this.sex = sex;
this.arr = [1,2,3];
}
Person.prototype.eat = function(){
console.log('吃饭饭');
}
// 子类 子构造函数
function Children(){}
// 原型链继承
Children.prototype = new Person('joth', 18, 'male');
Children.prototype.constructor = Children;//手动修改原型对应的构造函数 解决问题2
// Children具有了 Person的属性
var children1 = new Children();
var children2 = new Children();
// 问题1 所有实例化的对象中的属性的值不能被改变
console.log(children1.name, children2.name);
console.log(children1.arr, children2.arr);
children1.eat();
children2.eat();
// 改变一个实例化对象中的属性和方法 就会使所有的实例对象中的该属性或方法被改变
// 因为所有的属性和方法都被继承到了Children的原型上 都变为了共享的属性和方法
children1.arr.push(100);
console.log(children1.arr, children2.arr);
console.log(Children);
console.log(Children.prototype);
// 问题2 Children的原型的constructor不指向Children了 根据你的原型链 指向 父类的构造函数
console.log(children1 instanceof Children);true
console.log(children1.__proto__.constructor);//Person
</script>
对象冒充继承
组合继承
<script>
// 父类 父构造函数
function Person(name, age, sex){
this.name = name;
this.age = age;
this.sex = sex;
this.arr = [1,2,3];
}
Person.prototype.eat = function(){
console.log('吃饭饭');
}
// 子类的组合继承
// 将父类的构造函数的属性和方法通过对象冒充来继承给子类的构造函数,将父类的原型上的属性和方法采用原型链继承的方式继承给子类的原型
function Children(name, age, sex){
Person.call(this ,name, age, sex);
}
// 原型链继承
Children.prototype = new Person();
// 手动修改该原型的构造函数
Children.prototype.constructor = Children;
var children1 = new Children('tom', 8, 'male');
var children2 = new Children('lily', 12, 'female');
console.log(children1.name,children2.name);
children1.arr.push(100);
console.log(children1.arr,children2.arr);
children1.eat();
children2.eat();
// 由于我们采用了两次继承 那么在构造函数中的属性和方法被继承了2次 对象冒充时继承一次 原型链继承时又继承了一次 原型链继承时 我们没有传参 所以所有属性值都是undefined 由于构造函数中的属性比原型上的同名属性级别高 所有访问的是构造函数中的属性
console.log(children1)
</script>
寄生式组合继承
<script>
function inherit(Parent, Child){;//parent 父类 child 子类
// 建立中间宿主构造函数
function Super(){}
Super.prototype = Parent.prototype;
// 原型链继承中间宿主构造函数
Child.prototype = new Super();
// 手动修改子类的原型的构造函数
Child.prototype.constructor = Child;
}
// 父类 父构造函数
function Person(name, age, sex){
this.name = name;
this.age = age;
this.sex = sex;
this.arr = [1,2,3];
}
Person.prototype.eat = function(){
console.log('吃饭饭');
}
// 子类的寄生式组合继承
// 对象冒充继承
function Children(name, age, sex){
Person.call(this,name, age, sex)
}
// 封装带有中间宿主的原型链继承的函数
inherit(Person, Children);
var children1 = new Children('tom', 8, 'male');
console.log(children1);
</script>
原型和原型链
正则表达式
<script>
// 实例化创建 new RegExp(‘检索字符/正则表达式’,’修饰符’);
var reg = RegExp(/\d+/,'g')
// 字面量创建
var reg = /\d+/g
</script>
正则表达式的修饰符
<script>
// g glogal 全局匹配
var str = 'my name is joth,my age is 18,my school is csyz';
var reg = /my/g;
var nStr = str.replace(reg,'your');
console.log(nStr);
// i ignore 不区分大小写
var str = 'hello Hello HELLO hEllo hello heLLo hellO';
var reg = /hello/gi;
var arr = str.match(reg);
console.log(arr);
</script>
字符串和正则的检索方法
字符串的检索方法
var str = 'a1b2c3d4e5f6g7h8i9j';
// 字符串检索方法
// replace 根据正则替换原有字符串
var reg = /\d/g;
var nStr = str.replace(reg,'*');
console.log(nStr);
// split 根据某个字符串或正则将原字符串拆分为一个数组
var reg = /\d/g;
var arr = str.split(reg);
console.log(arr);
// search 找到对应的字符串 返回下标 如果找不到就 返回-1 等同于 indexOf
var reg = /18/;
console.log(str.search(reg));
// match 查找到匹配正则的字符串 返回数组(当非全局模式下只匹配找到的第一个字符串,形成数组中会包含关于该字符串及数组的信息,如果是全局则将所有匹配的字符串形成一个数组返回)
var reg = /\d/;
var reg1 = /\d/g;
console.log(str.match(reg));
console.log(str.match(reg1));
正则的检索方法
<script>
var str = 'a1b2c3d4e5f6g7h8i9j';
// 字符串检索方法
// replace
var reg = /\d/g;
var nStr = str.replace(reg,'*');
console.log(nStr);
// split 将数字做为一个拆分的分隔符
var reg = /\d/g;
var arr = str.split(reg);
console.log(arr);
// search 找到对应的字符串 返回下标 如果找不到就 返回-1 等同于 indexOf
var reg = /18/;
console.log(str.search(reg));
// match 查找到匹配正则的字符串 返回数组(当非全局模式下只匹配找到的第一个字符串,形成数组中会包含关于该字符串及数组的信息,如果是全局则将所有匹配的字符串形成一个数组返回)
var reg = /\d/;
var reg1 = /\d/g;
console.log(str.match(reg));
console.log(str.match(reg1));
// 正则检索方法
// test 测试 如果匹配返回真 不匹配返回假
var str = 'aabbcc';
var reg = /aabdbcc/;
console.log(reg.test(str));
// exec
var str = 'a1b2c3d4';
var reg = /\d/;
var reg1 = /\d/g;
console.log(reg.exec(str));
console.log(reg1.exec(str));//1
console.log(reg1.lastIndex);//2 下一次匹配的起始索引
console.log(reg1.exec(str));//2
console.log(reg1.lastIndex);//4
console.log(reg1.exec(str));//3
console.log(reg1.lastIndex);//6
console.log(reg1.exec(str));//4
console.log(reg1.lastIndex);//8
console.log(reg1.exec(str));//null
console.log(reg1.lastIndex);//0
</script>
正则对象字符
<script>
// . 匹配除换行符以外的任意字符
var str = '\nas23@4de';
var reg = /./g;
console.log(str.match(reg));//["a", "s", "2", "3", "@", "4", "d", "e"]
// [] 匹配一个区间范围的字符串如:[0-9] [0-9a-z] [0-9a-zA-Z]
var str = '23sDr43s45wSdf345sd43rsr';
var reg = /[0-9]/g;
var reg1 = /[a-zA-Z]/g;
console.log(str.match(reg));//["2", "3", "4", "3", "4", "5", "3", "4", "5", "4", "3"]
// [^] 匹配非区间范围的字符串 如:[^0-9] [^0-9a-z] [^0-9a-zA-Z]
var str = '23srwW4lkj5#wErlkj@';
var reg = /[^0-9a-z]/g;
console.log(str.match(reg));//["W", "#", "E", "@"]
// \d 匹配数字 等价于 [0-9]
var str = '23sDr43s45wSdf345sd43rsr';
var reg = /\d/g;
var reg1 = /[^\d]/g;
console.log(str.match(reg));
console.log(str.match(reg1));
// \D 匹配非数字字符串 ==》 [^\d]等价于[^0-9]
var str = '23sDr43s45wSdf345sd43rsr';
var reg = /\D/g;
console.log(str.match(reg));
// \w 匹配数字 字母 下划线
var str = '132wAw_s#@3cD';
// var str1 = 'asdflkj1sadlkfjsfd';
// var reg1 = /\d/g;
var reg = /\w/g;
// console.log(reg1.test(str1));//true 只要字符串包含该类型字符 就返回真
console.log(str.match(reg));
// \W 匹配非数字 字母 下划线
var str = '132wAw_s#@3cD';
var reg = /\W/g;
console.log(str.match(reg));//["#", "@"]
// \s 匹配空白字符、空格、制表符和换行符
var str = 'aa bb cc dd';
var reg = /\s/g;
console.log(str.replace(reg,'*'));//aa*bb*cc*dd
// \S 匹配非空白字符串
// ^以什么开始 $以什么结尾
var str = '5671346575672341238aaa';
var str2 = '123454563453468323458'
var reg = /^1\d+8$/
console.log(reg.test(str));//false 包含1开头8结尾的数字字符串 要求时必须用1 开头 用8 结束
console.log(reg.test(str2));//true
// \b 匹配单词边界
var str = 'this is his apple';
var reg = /\bis\b/g;
console.log(str.replace(reg,'IS'));
// \B 匹配非单词边界
var str = 'this is his apple';
var reg = /\Bis\b/g;
console.log(str.replace(reg,'IS'));
// ? 匹配0个或1个
var str = '123123123';
var str1 = 's123123123';
var str2 = 'asdf123123123';
var reg = /^[a-z]?\d+$/;
console.log(reg.test(str));//true
console.log(reg.test(str1));//true
console.log(reg.test(str2));//false
// * 匹配0个或多个
var str = '123123123';
var str1 = 's123123123';
var str2 = 'asdf123123123';
var reg = /^[a-z]*\d+$/;
console.log(reg.test(str));//true
console.log(reg.test(str1));//true
console.log(reg.test(str2));//true
// + 连续匹配一个或多个
var str = '23sDr43s45w7Sdf345sd43rsr';
var reg = /\d/g;
var reg1 = /\d+/g;
console.log(str.match(reg));
console.log(str.match(reg1));
// (a|b|c) 分组匹配 就在分组中的任意一个 | 代表或
var str = 'a123123123';
var str1 = 'z123123123';
var reg = /^(a|b|c)\d+$/;
console.log(reg.test(str));
console.log(reg.test(str1));
// (abc)+
var str = 'abc12313123';
var str1 = 'abcabcabc12312123';
var reg = /^(abc)+\d+$/
console.log(reg.test(str));
console.log(reg.test(str1));
// {} 个数取值范围 {0,1}匹配0次或1次 {m,n}匹配m次到n次 {n} 必须匹配n次
var str = 'aa1111';
var str1 = 'aaa1';
var str2 = 'aaaa123123'
var str3 = 'a123123'
var reg = /^a{2,4}\d+$/;
console.log(reg.test(str));
console.log(reg.test(str1));
console.log(reg.test(str2));
console.log(reg.test(str3));
// 注册 判断 手机号码是否符合规则 邮箱是否符合规则
</script>
<script>
// 分组 $1 $2....自动对每个分组进行了编号
var str = '07-31-2020';
var reg = /^(\d\d)-(\d\d)-(\d\d\d\d)$/;
console.log(reg.exec(str));
console.log(RegExp.$1,RegExp.$2,RegExp.$3);
console.log(str.replace(reg,'$3年$1月$2日'));
// 座机号码 正则表达式 区号-电话号
// 前瞻后顾
// 正向预肯定查找 ?= 匹配后边确定的内容之前的字符串(后边是什么的字符串被匹配)
var path1 = 'path/hello.html';
var path2 = 'path/nodata.html';
var path3 = 'path/index.html';
var reg = /\w+(?=\.html$)/
console.log(path1.match(reg));
console.log(path2.match(reg));
console.log(path3.match(reg));
var str = '中国人';
var str1 = '美国佬';
var str2 = '日本人';
var reg = /.+(?=人$)/;
console.log(str.replace(reg,'亚洲'));
console.log(str1.replace(reg,'亚洲'));
console.log(str2.replace(reg,'亚洲'));
// 反向预肯定查找 ?<= 匹配前边确定的内容之后的字符串 (前边是什么的 字符串被匹配)
var path1 = 'path/hello.html';
var path2 = 'path/nodata.html';
var path3 = 'path/index.html';
var reg = /(?<=path\/)\w+/
console.log(path1.match(reg));
console.log(path2.match(reg));
console.log(path3.match(reg));
var str = '中国人';
var str1 = '美国佬';
var str2 = '日本人';
var reg = /(?<=日本).+/
console.log(str1.replace(reg,'鬼子'));
console.log(str2.replace(reg,'鬼子'));
// 正向预否定查找 ?! 匹配后边不是确定的内容之前的字符串 (后边不是什么的字符被匹配)
var str = 'a,1,b,2,c,3,' // a=1=b=2=c=3
// 把字符串改成 a=1,b=2,c=3,
var reg = /,(?![a-z]|$)/g;// 匹配逗号 后边是非字母或是没有字符的这样的,
console.log(str.replace(reg,'='));
var str = 'abc';
var str1 = 'abb9';
var str2 = 'abcd';
var reg = /.+(?![a-z]|$)/;
console.log(str.replace(reg,'欧美'));
console.log(str1.replace(reg,'欧美'));
console.log(str2.replace(reg,'欧美'));
// 反向预否定查找 ?
var str = 'a,1,b,2,c,3,'
var reg = /(?<!\d),/g//匹配逗号 前边不是数字的逗号
console.log(str.replace(reg,'='));
</script>
匿名函数
函数分类:
<script>
// 当你直接定义一个没有名字的函数时 提示错误了 而且也无法调用执行
// function(){
// console.log('匿名');
// }
//匿名函数的自执行 (匿名函数)()
// (function(){
// console.log('匿名');
// })()
function fn(){
console.log('fn');
}
console.log(fn)
fn()
;(function(){
console.log('匿名');
})()
// fn()()();
// ;(function fn(){
// console.log('fn');
// })()
// function fn(){
// return function(){
// return function(){
// console.log('123');
// }
// }
// }
// fn()()();
// 匿名函数的传参
var result = (function(a){
return a * a;
})(15)
console.log(result);
</script>
闭包
什么是闭包:可以读取其他函数内部的变量的函数(函数套函数,子函数可以访问父函数中的内部变量) 本质上闭包就是将内部函数和外部函数链接起来的桥梁。
<script>
// function fnn(){
// console.log(a);
// }
// window.onload = function(){
// var a = 10;
// function fn(){
// console.log(a)
// }
// }
function a(){
var aaa = 100;
console.log(aaa);
}
a();
// 因为返回的内层函数 要用到父级函数中的变量a 所以导致 父级函数执行完成后 里边变量a 不能被系统做垃圾回收 他会一直存在 需要手动回收
function fn(){
var a = 10;
return function(b){
console.log(a + b)
}
}
var fnn = fn();
fnn(8);
fnn(24);
</script>
闭包模拟私有属性
<script>
// public 公有 private 私有
function Person(name){
this.name = name; //公有
var money = 500; //私有
// 设置私有属性的接口
return {
name: this.name,
get:function(){
return money;
},
set:function(cash){
money += cash;
}
}
}
var person1 = new Person('joth');
console.log(person1.name);
console.log(person1.get());//通过接口访问和修改私有属性
person1.set(500);
console.log(person1.get());
</script>
json数据和对象的区别:json 是一种轻量级的数据交换格式。具有对象结构的字符串数据,在json中所有的键和字符串的值 都要用双引号包裹
get和post:
ajax的步骤
//get
window.onload = function(){
var oDiv = document.getElementsByTagName('div')[0];
// get方式
// 创建ajax对象
var oAjax = new XMLHttpRequest(); // ie6 不支持该对象 ie6下 var oAjax = ActiveXObject('Microsoft.XMLHTTP');
// 服务器连接设置
oAjax.open('GET','./mytxt.txt',true); //最后一个参数 async:是否为异步操作 默认为true 异步 如果设置为false 则为同步
// get 方式 如果有数据需要发送 那么 我们需要将url地址变为url?page=1&fl=1
// 发送数据开始和服务器交互
oAjax.send();
oAjax.onreadystatechange = function(){//注册ajax事件 当ajax的状态发生变化
// console.log(oAjax.readyState);// 2 3 4
if(oAjax.readyState == 4){// 当状态变为4 表白 整个ajax已经和服务器完成了交互
if(oAjax.status == 200){//200代表访问成功并回传了对应的数据 404 找不到 http 状态码
oDiv.innerHTML = oAjax.responseText;//将获取到的服务器返回的数据(数据类型为字符串)显示到div中
}else{
alert('Error:' + oAjax.status);// 提示错误状态码
}
}
}
}
//post
window.onload = function(){
var oDiv = document.getElementsByTagName('div')[0];
// post方式
// 创建ajax对象
var oAjax = new XMLHttpRequest(); // ie6 不支持该对象 ie6下 var oAjax = ActiveXObject('Microsoft.XMLHTTP');
// 服务器连接设置
oAjax.open('post','./mytxt.txt',true); //最后一个参数 async:是否为异步操作 默认为true 异步 如果设置为false 则为同步
// 发送数据开始和服务器交互
oAjax.setRequestHeader('Content-type','appliction/x-www-form-urlencoded');//请求头数据类型的设置
oAjax.send();
// post如果要发送数据 则是在 send中来发送 如 oAjax.send('user=aaa&pass=123123')
oAjax.onreadystatechange = function(){//注册ajax事件 当ajax的状态发生变化
// console.log(oAjax.readyState);// 2 3 4
if(oAjax.readyState == 4){// 当状态变为4 表白 整个ajax已经和服务器完成了交互
if(oAjax.status == 200){//200代表访问成功并回传了对应的数据 404 找不到 http 状态码
oDiv.innerHTML = oAjax.responseText;//将获取到的服务器返回的数据(数据类型为字符串)显示到div中
}else{
alert('Error:' + oAjax.status);// 提示错误状态码
}
}
}
}
eval和JSON.parse/JSON.stringify
<script>
// var str = 'function aa(){console.log("aaa")};aa();';
// eval(str);//将字符串转换为js代码
// /*
// function aa(){
// console.log('aaa');
// };
// aa();
// */
// var str1 = '["a","b","c","d"]';
// var json = '{"name":"joth","age":18,"sex":"male"}';
// console.log(str1.length);
// var arr = eval(str1);
// console.log(arr, arr.length);
// console.log(eval(json));//json eval不支持
//JSON.parse
// var str = 'function aa(){console.log("aaa")};aa();';
// var str1 = '["a","b","c","d"]';
// var json = '{"name":"joth","age":18,"sex":"male"}';
// // console.log(JSON.parse(str));//JSON.parse 不支持js代码字符串 必须是某种数据
// console.log(JSON.parse(str1));
// console.log(JSON.parse(json));//json格式转换为对象
//JSON.stringify
var obj = {
name: 'joth',
age: 18,
sex: 'male'
}
var arr = ['a','b','c'];
console.log(JSON.stringify(obj));
console.log(JSON.stringify(arr));
</script>
artTemplate
<script src="./template-web.js"></script>
<!-- 建立模板 id的作用是最后将模板和数据关联起来-->
<script type="text/html" id="temp">
<h4>{{title}}</h4>
{{if count}}
<ul>
{{each list item i}}
<li>{{i}}----{{item}}</li>
{{/each}}
</ul>
一共保存有<span>{{count}}</span>本书。
{{else}}
<span>当前没有数据</span>
{{/if}}
</script>
<script>
window.onload = function(){
var oDiv = document.getElementById('box');
var data = {
title: '世界名著书目',
list: ['西游记','三个火枪手','茶花女','巴黎圣母院','挪威森林','三体']
}
// 给data对象添加属性 count 值为 list的长度
data.count = data.list.length;
var html = template('temp',data);
oDiv.innerHTML = html;
}
</script>
touch的基本事件
ontouchstart 触碰开始(手指按到了屏幕上)
ontouchmove 开始移动(手指在屏幕上滑动)
ontouchend 触碰结束(手指离开)
<script>
window.onload = function(){
var oDiv = document.getElementById('box');
oDiv.addEventListener('touchstart',function(){
console.log('手指按下');
})
oDiv.addEventListener('touchmove',function(){
console.log('手指滑动');
})
oDiv.addEventListener('touchend',function(){
console.log('手指离开')
})
}
</script>
touch事件必须使用addEventListener
<script>
window.onload = function(){
var oDiv = document.getElementById('box');
oDiv.addEventListener('touchstart',function(){
console.log('手指按下');
})
oDiv.onmousedown = function(){
console.log('鼠标按下');
}
}
</script>
pc端事件比移动端慢300ms
点透问题
<script>
window.onload = function(){
var oDiv = document.getElementById('box');
oDiv.addEventListener('touchstart',function(){
this.style.display = 'none';
})
}
</script>
touch事件对象
<script>
window.onload = function(){
var oDiv = document.getElementById('box');
oDiv.addEventListener('touchstart',function(ev){
console.log(ev);
var touch = ev.changedTouches[0];//当前手指列表中的第一个指头
console.log(touch);
})
}
</script>
DOMContentLoaded
//rem计算js
;(function(doc, win){
var docEl = doc.documentElement,//根元素 html
//orientationchange事件在设备的纵横方向改变时触发
resizeEv = 'orientationchange' in win ? 'orientationchange' : 'resize',//设备尺寸发生变化
dW = 750,//设计稿宽度---改 你的设计稿是多少 这就写多少
reCalc = function(){
var clinetW = docEl.clientWidth;//设备可视区的宽
if(!clinetW) return;
if(clinetW >= dW){
// 当设备可视区宽大于了设计稿的宽
docEl.style.fontSize = '100px';
docEl.style.width = dW + 'px';//将设计稿的宽给到 html
docEl.style.margin = '0 auto';//居中
}else{
docEl.style.fontSize = 100 * (clinetW / dW) + 'px';
}
}
if(!doc.addEventListener) return;//如果文档不支持事件绑定 就不支持就返回不执行
win.addEventListener(resizeEv, reCalc, false);
doc.addEventListener('DOMContentLoaded', reCalc, false);//页面结构加载完成后执行reCalc函数
})(document, window)
// 使用方法 用设计稿的元素的宽/100;
Touch.js
webkit内核浏览器专用
语法:touch.on(元素(元素对象或 字符串选择器),事件,事件处理函数)
事件:
<script>
window.onload = function(){
var oDiv = document.getElementById('box');
touch.on(oDiv, 'tap', function(){
console.log('我被单击了');
})
touch.on(oDiv, 'doubletap', function(){
console.log('我被双击了');
})
touch.on(oDiv, 'hold', function(){
console.log('我被压了500年');
})
}
</script>
touchJs事件委托
语法:touch.on(父元素(元素对象或 字符串选择器),事件,目标元素(字符串选择器),事件处理函数)
<script>
window.onload = function(){
var oList = document.getElementById('list');
touch.on(oList,'tap','li',function(){
console.log(this.innerHTML);
})
}
</script>
touch事件对象
jq是一个js库,是极大简化了原生js开发(操作dom,遍历元素,ajax,动画–运动框架)
jQuery 与 $ 的关系:$是jQuery的简写
onload和ready的区别
<script>
// 原生使用onload 文档结构和资源
// window.onload = function(){
// console.log($('#box'));
// }
// window.onload = function(){
// }
//jq使用 ready 文档结构
// $(document).reday(function(){// 当做window.onload来使用 但实际上它的等待加载 类似 DOMContentLoaded
// })
// // 简写
// $(function(){
// })
// 可以重复多个
// window.onload = function(){
// var oDiv = document.getElementById('box');
// console.log(oDiv);
// }
window.onload = function(){
var oDiv = document.getElementById('abox');
console.log(oDiv);
}
$(document).ready(function(){
console.log($('#box'));
})
$(function(){
console.log($('#abox'));
})
</script>
jq中获取的元素 不再是DOM。原生方式获取的元素为DOM 而jq中 获取到的DOM被jq进行包装形成一个jq对象。
$的权限让出
<script>
$(function(){
jQuery.noConflict();//让出$使用权
$('欢迎光临!');//aaa.js
// jQuery('#box').html('我的零食店!');//$被让出,那么我们可以使用jQuery来继续操作jq代码
// 如果让出之后,我还是希望使用$来继续操作jq 那么需要做一个闭包
;(function($){//将jq的jQuery 传给匿名函数的形参$ 这时在该匿名函数中$又代表 jQuery
$('#box').html('我的零食店!')
})(jQuery)
})
</script>
jq选择器— css中怎么写 这就怎么写
<script>
$(function(){
// 层次选择器
console.log($('ul li'));//ul下的所有li 包含ol下的li
console.log($('ul>li'));//第一层级(子级)下的li 不包含ol下的li ol下的li 叫 后代
console.log($('#lili+li'));//id为lili的下一个兄弟
console.log($('#lili~li'));//id为lili下的所有的兄弟
// 过滤选择器
// 基本过滤选择器
console.log($('li:first'));//li的第一个
console.log($('li:last'));//li最后一个
console.log($('li:not(.li1)'));//选择所有不带class为li1的li 包含后代
console.log($('li:odd'));//选择所有下标奇数li 下标是从0开始 0被算作偶数
console.log($('li:even'));//选择所有下标偶数li 下标是从0开始 0被算作偶数
console.log($('li:eq(8)'));//选择下标为5的li
console.log($('li:gt(8)'));//选择下标大于8的li
console.log($('li:lt(8)'));//选择下标小于8的li
// 属性过滤选择器
console.log($('li[name]'));//选择有name属性的li 无论属性的值是什么
console.log($('li[name=joth]'));//选择name属性的值是某个固定值的li
console.log($('li[name!=joth]'));//选择name属性值不等于joth的li 没有name属性的也被包含了
console.log($('li[name^=j]'));//选择name属性的值以j开头的li
console.log($('li[name$=e]'));//选择name属性的值以e结尾的li
console.log($('li[name*=o]'));//选择name属性的值包含o的li
})
</script>
表单选择器
<script>
$(function(){
// 表单选择器
console.log($('input'));//input标签
console.log($(':input'));//基本上就是所有表单元素
console.log($(':checked'));//选择被选中的表单元素 checkbox radio select
// 按表单类型选择
console.log($(':text'));//选择所有type为text的文本框
console.log($(':password'));//类型为密码的文本框
console.log($(':checkbox'));//选择所有的多选框
console.log($('textarea'));// 文本域标签
console.log($(':submit'));//为提交按钮的表单元素
})
</script>
节点遍历操作
获取子元素:
获取兄弟节点
获取父节点
<script>
$(function(){
// 子节点
console.log($('#box').children());
console.log($('#box').children('span'));
// 兄弟节点
console.log($('.div1').prev());//该元素的上一个兄弟节点
console.log($('.div1').prevAll());//该元素的之前的所有兄弟节点
console.log($('.div1').next());//该元素的下一个兄弟节点
console.log($('.div1').nextAll());//该元素的之后的所有兄弟节点
console.log($('.div1').siblings());//该元素的所有兄弟节点
console.log($('.div1').siblings('p'));//该元素的所有p兄弟节点
// 获取父节点
console.log($('#link').parent());//获取该元素的父节点
console.log($('#link').parents());//获取该元素的所有祖先节点
console.log($('#link').parents('div'));//获取该元素的祖先节点中的div
})
</script>
过滤节点
<script>
$(function(){
console.log($('ul').find('span'));
console.log($('li').filter('.li1'));//过滤选取
console.log($('li').filter('.aaa'));
console.log($('li').not('.li1'));//过滤排除
})
</script>
jq属性操作
<script>
$(function(){
// 获取属性值
console.log($('#box').attr('title'));
// 设置
$('#box').attr('title','bbbbox');
// 对象参数设置
$('#box').attr({name:'joth',age:18,sex:'male'});
// 删除属性
$('#box').removeAttr('title');
// 表单元素checkbox的checkd属性
// console.log($(':checkbox').attr('checked'));
// 获取
console.log($(':checkbox').prop('checked'));//false
// 设置
$(':checkbox').prop('checked',true);
})
</script>
jq操作class
</style>
<!-- <script>
window.onload = function(){
var oDiv = document.getElementById('box');
var oBtn = document.getElementsByTagName('button')[0];
var flag = true;
oBtn.onclick = function(){
if(flag){
oDiv.className = 'blue';
}else{
oDiv.className = 'red';
}
flag = !flag;
}
}
</script> -->
<script src="./jquery.min.js"></script>
<script>
$(function(){
$('button').click(function(){
if($('#box').hasClass('red')){
$('#box').removeClass('red').addClass('blue');
}else{
$('#box').removeClass('blue').addClass('red');
}
})
})
</script>
<script>
$(function(){
$('button').click(function(){
$('#box').toggleClass('blue');
})
})
</script>
<script>
$(function(){
console.log($('#box').hasClass('one'));
console.log($('#box').is('one'));
$('#box').addClass('one');
$('#box').addClass('tow');
$('#box').removeClass('on');
})
</script>
jq操作样式
<script>
$(function(){
// 获取样式
console.log($('#box').css('width'));//'100px'
// 设置
$('#box').css('border','10px solid #000');
// 对象设置
$('#box2').css({width:100,height:'100px',background:'blue'});
})
</script>
html 文本及值的相关操作
<script>
$(function(){
// 获取内容
console.log($('#box').html());
console.log($('#box').text());
console.log($(':text').val());
// 设置内容
$('#box').html('奔流到海不复回');
// $('#box').text('奔流到海不复回');
$(':text').val('妙哉!妙哉!');
})
</script>
$下的常用方法
<script>
var arr = ['a','b','c','d','e'];
$.each(arr,function(i,item){
console.log(i + '---' + item.toUpperCase());
})
var nArr = $.map(arr,function(item, i){
return item.toUpperCase();
})
console.log(nArr);
var obj = {
name:'joth',
age:'eighteen',
sex:'male'
}
$.each(obj,function(key,value){
console.log(key + '---' + value.toUpperCase());
})
</script>
深拷贝和浅拷贝
深浅拷贝主要针对于引用类型来说的,当赋值引用类型时 会直接进行传址,导致多个变量指向同一地址 共享使用,当某个对象修改了内容会导致所有对象都使用修改后的数据这就是浅拷贝。如果要深拷贝,需要将每一项数据都进行克隆拷贝到一个新对象中。
function deepClone(obj){
// 判断是不是array 创建的对象 就不同 [] {}
var cloneObj = Array.isArray(obj) ? [] : {};
if(obj && typeof obj == 'object'){//参数存在 且参数类型为object
for(var key in obj){//进行循环
if(obj.hasOwnProperty(key)){//如果当前要进行遍历的 属性是对象的构造函数创建的属性则返回true 继续向下进行 不是则返回false就不进行下边的复制操作了
if(obj[key] && typeof obj[key] == 'object'){//如果obj的某个属性又是对象
cloneObj[key] = deepClone(obj[key]);// 递归调用复制函数继续进行forin的循环赋值 如果在循环中再次出现对象属性 继续递归调用 直到所有的属性都是基本类型时
}else{
// 如果属性值为基本类型 则直接 复制
cloneObj[key] = obj[key];
}
}
}
}
return cloneObj;
}
$.extend()
<script>
var obj = {
a:10
}
var obj1 = {
b : 20
}
var obj2 = {
c: 30
}
var obj3 = {
d:40
}
// $.extend(obj,obj1,obj2,obj3);
// console.log(obj);
var objAll = $.extend({},obj,obj1,obj2,obj3);
console.log(obj, objAll)
var obj = {
name:'joth',
age:18,
sex:'male',
body:{
weight:'65kg',
height:'174cm',
eyes:{
left:'1.0',
right:'1.2'
}
},
eat:function(){
console.log('吃饭饭');
}
}
// jq的浅拷贝
// var nObj = $.extend({},obj);
// obj.body.eyes.right = '1.0';
// console.log(obj, nObj)
// jq的深拷贝
var nObj = $.extend(true,{},obj);
obj.body.eyes.right = '1.0';
console.log(obj, nObj)
</script>
BOM 操作
元素的宽高
原生元素的宽高
jq中元素的宽高获取和设置
<script>
$(function(){
// 内容宽
console.log($('#box').width());//100
// 可视宽
console.log($('#box').innerWidth());//160
// 占位宽
console.log($('#box').outerWidth());//180
// 整个宽 width+ padding+ border+ margin
console.log($('#box').outerWidth(true));//280
// 设置宽高
// $('#div1').width(100).height(100);
$('#div1').innerWidth(100).innerHeight(100);
$('#div1').outerWidth(100).outerHeight(100);
$('#div1').outerWidth(100,true).outerHeight(100,true);
// 浏览器可视区的宽高
console.log($(window).height());
// 文档的宽高
console.log($(document).height());
})
</script>
元素的位置
<script>
$(function(){
console.log($('#box').position());
console.log($('#box').offset());
console.log($('#box').position().top)
})
</script>
滚动条
//jd楼层
<script>
$(function(){
// 窗口滚动条滚动
$(window).scroll(function(){
// 遍历所有的div版块
$('#box div').each(function(i, el){
// 如果 滚动条卷走的高度 大于等于了 某个版块的到文档顶部的top值
if($(window).scrollTop() >= $(el).offset().top){
// 找到index值相等的li 给该li加上样式on 然后将该li的所有兄弟移除样式on
$('#menu ul li').eq($(this).index()).addClass('on').siblings().removeClass('on');
}else{//如果 滚动条卷走的高度 小于了 某个版块到文档顶部的top值 那么将该div对应的li的样式 移除
$('#menu ul li').eq($(this).index()).removeClass('on');
}
})
})
// 隐式迭代
$('#menu ul li').click(function(){
// 当点击了某个li
// 计算该li的index值对应的div的到文档顶部的top值
var iTop = $('#box div').eq($(this).index()).offset().top;
// 该被点击的li获得样式on 将该li的兄弟移除样式on
$(this).addClass('on').siblings().removeClass('on');
// 将滚动条卷走的高度设置给刚刚计算的top值 也就是将滚动条定位到该li对应的版块的位置
$(window).scrollTop(iTop);
})
})
</script>
jq中DOM 操作
创建节点:用$(‘标签’)
添加节点:
插入节点
替换节点
复制节点
删除节点
<script>
$(function(){
// 创建节点
var oLi = $('- 火影忍者
');
console.log(oLi);
// 添加节点
// $('ul').append(oLi);//给ul添加一个li
// oLi.appendTo($('ul'));//将一个li添加到ul中
// 插入元素
// 之前插入
// oLi.insertBefore($('ul li:eq(2)'));
// $('ul li:eq(2)').before(oLi);
// 之后插入
// oLi.insertAfter($('ul li:eq(2)'));
// $('ul li:eq(2)').after(oLi);
// 替换
// $('ul li:eq(3)').replaceWith(oLi);
// oLi.replaceAll($('ul li:eq(3)'));
// 复制
// var cloneLi = null;
// $('ul li').click(function(){
// cloneLi = $(this).clone(true);
// $('ul').append(cloneLi);
// })
// 删除
// $('ul li').click(function(){
// console.log($(this).html());
// })
// // var oLi = $('ul li').eq(0).remove();//不带事件的
// var oLi = $('ul li').eq(0).detach();//带事件的删除
// $('ul').append(oLi);
})
</script>
jQuery 中的事件
<script>
$(function(){
// $(document).contextmenu(function(){
// console.log('right');
// })
// 事件对象
$(document).click(function(ev){
console.log(ev);
/*
ev.clientX/ev.clientY 鼠标和浏览器可视区的x y轴的距离
ev.delegateTarget: 事件绑定的目标
ev.currentTarget:当前触发事件的目标
ev.offsetX/ev.offsetY: 鼠标和触发事件的元素的X Y轴的距离
ev.pageX/pageY: 鼠标和当前文档的X Y轴的距离
ev.screenX/screenY: 鼠标在屏幕上X Y轴的距离
ev.originalEvent: 原生的事件对象上的属性
ev.which: 确定鼠标的那个键(事件 mousedown) 1左键 2中滚轮按下 3右键
*/
})
$(document).mousedown(function(ev){
console.log(ev.which);
})
})
</script>
jq事件绑定
<script>
$(function(){
// 事件绑定
// $('ul li').on('click',function(){
// console.log($(this).html());
// })
// 给一个元素 绑定多个事件 触发同一个事件处理函数
// $('ul li').on('click mouseenter contextmenu',function(){
// console.log('各种事件触发了该函数');
// })
// 对象参数的数据绑定--- 多个事件对应多个事件处理函数
// $('ul li').on({
// 'click':function(){
// console.log('单击');
// },
// 'mouseenter':function(){
// console.log('鼠标移入');
// },
// 'contextmenu':function(){
// console.log('右键点击');
// }
// })
// 自定义事件
// $('ul li').on('haha',function(){
// console.log('事件哈哈被触发');
// })
// $('ul li').trigger('haha');
// 事件委托
// $('ul li').click(function(){
// console.log($(this).html());
// })
// $('button').click(function(){
// $('ul').append($('- 哈哈哈
'));
// })
// $('ul').on('click','li',function(ev){
// console.log(ev);
// console.log(ev.currentTarget);// 事件触发的目标 被点击的li
// console.log(ev.delegateTarget);//事件绑定的目标 ul
// console.log($(this).html());
// })
// $('button').click(function(){
// $('ul').append($('- 哈哈哈
'));
// })
// 取消事件绑定
// $('#btn').on('click',function(){
// console.log('点击触发了')
// })
// $('#offbtn').click(function(){
// $('#btn').off('click');
// })
// $('#btn').on('click',function(){
// console.log('点击触发了')
// })
// $('#btn').on('click',function(){
// console.log('第二个点击触发了')
// })
// $('#offbtn').click(function(){
// $('#btn').off('click');
// })
// 事件的命名空间
// $('#btn').on('click.a',function(){
// console.log('点击触发了')
// })
// $('#btn').on('click.b',function(){
// console.log('第二个点击触发了')
// })
// $('#offbtn').click(function(){
// $('#btn').off('click.b');
// })
// 只绑定一次的事件绑定
// $('#btn').one('click',function(){
// console.log('我真的还想再点500次');
// })
// 模拟绑定一次
// $('#btn').on('click',function(){
// console.log('我真的还想再点500次');
// $(this).off('click');
// })
// 合成事件
/*
onmouseover---onmouseout 冒泡
onmouseenter--- onmouseleave 不会冒泡 合成事件使用
*/
$('ul li').hover(function(){
// 鼠标移入触发
$(this).css('background','red');
},function(){
// 鼠标移出触发
$(this).css('background','');
})
})
</script>
jQuery 中的动画
jq中的固定动画效果 参数(duration–持续时间,easing–运动效果 linear swing ,callback—当动画执行完毕之后的回调函数)
<script>
$(function(){
// show/ hide
// $('button:eq(0)').click(function(){
// $('div').show(800);
// })
// $('button:eq(1)').click(function(){
// $('div').hide(800);
// })
// 隐藏显示切换
// $('button:eq(0)').click(function(){
// $('div').toggle(800);
// })
// 淡入淡出
// $('button:eq(0)').click(function(){
// $('div').fadeIn(800);
// })
// $('button:eq(1)').click(function(){
// $('div').fadeOut(800);
// })
// 淡入淡出的切换
// $('button:eq(0)').click(function(){
// $('div').fadeToggle(800);
// })
// 滑出滑入
// $('button:eq(0)').click(function(){
// $('div').slideDown(800);
// })
// $('button:eq(1)').click(function(){
// $('div').slideUp(800);
// })
// 滑出滑入切换
// slideToggloe()
})
</script>
jq的自定义动画
<script>
$(function(){
// 基本动画
// $('button').click(function(){
// $('div').animate({width:300},600,function(){
// console.log('我到了,你呢?');
// })
// })
// 累加动画
// $('button').click(function(){
// $('div').animate({width: '+=50'},600,function(){
// console.log('一步一步向前走');
// })
// })
// 多属性一起运动
// $('button').click(function(){
// $('div').animate({width:300,height:300},600,function(){
// console.log('我到了,你呢?');
// })
// })
// 链式运动
// $('button').click(function(){
// $('div').animate({width:300},600)
// .animate({height:300},400)
// .animate({opacity:.5},200)
// })
$('button').click(function(){
$('div').animate({width:300},600,function(){
$(this).animate({height:300})
})
})
})
</script>
动画队列
<script>
$(function(){
$('button').click(function(){
// $('div').animate({width:400},1000)
// .css({background:'yellow'})//将css的设置 插入动画队列中 按照动画队列的顺序来执行
// .animate({height:400},1000);
// 动画队列 将一个非动画的操作加入到动画队列中 使用 queue
$('div').animate({width:400},1000)
.queue(function(next){
$(this).css({background:'yellow'});
// queue插入动画队列后 要继续执行动画队列 需要一个参数next 然后在最后 调用next方法
next();//继续执行后续动画队列中的动画
})
.animate({height:400},1000);
})
})
</script>
判断是否处于动画状态
停止动画和完成动画
<script>
$(function(){
$('button').eq(0).click(function(){
$('div').animate({width:400},800).animate({height:400},800)
})
$('button').eq(1).click(function(){
$('div').stop(true,true)
})
$('button').eq(2).click(function(){
$('div').finish();
})
})
</script>
jq中的ajax
原生的ajax
get和post区别
jq中的ajax
<script>
$(function(){
$.ajax({
type:'get',
url:'./mydata.json',
success:function(res){
show(res);
}
})
function show(arr){
$.each(arr,function(i,item){
$('ul').append($('- +
item.href + '">' + item.title + '
get 和post方法
<script>
//jq的 data传递数据支撑字符串 对象 'page=1&count=10' {page:1,count:10}
$.get('./mydata.json',function(res){
console.log(res);
})
// post 和get 效果一样
// $.post('./mydata.json',{page:1},function(res){
// console.log(res);
// })
</script>
跨域jsonp
jq的插件
jq插件分为两种
<script>
// 类级别插件 将字符串开头 或者结尾的空格取消
var str = ' hello ';
var arr = [1,1,1,2,2,2,3,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8];
// console.log(str.trim());
$.extend({
startTrim:function(str){
var reg = /^\s+/;
str = str.replace(reg,'');
return str;
},
endTrim:function(str){
var reg = /\s+$/;
str = str.replace(reg,'');
return str;
},
removal:function(arr){
var json = {};
var nArr = [];
$.each(arr,function(i,val){
if( !json[val]){
json[val] = 1;
nArr.push(val);
}
})
return nArr;
}
})
console.log($.removal(arr))
</script>
<script>
// $.each(arr,function) //类级别 工具级方法
// $('div').each(fucntion()) //对象级别 对象的方法
$.fn.extend({
'changeColor':function(oddColor,evenColor){
// console.log(this);// jq对象 tbody
this.children(':odd').css({background:oddColor});
this.children(':even').css({background:evenColor});
return this;
}
})
$(function(){
$('table tbody').changeColor('pink','green').css({fontSize:'18px'})
// $('table tbody').click(function(){
// console.log(this);// ... 原生DOM tbody
// })
$('ul').changeColor('#ccc','skyblue').children().css({border:'1px dotted #000'})
})
</script>
Zepto.js
是专门用于移动端的一个js库 它的API基本上和jq是一样,只针对移动端,所以不兼容低版本浏览器。
<script src="./zepto.min.js"></script>
<script src="./touch.js"></script>
<script>
$(function(){
$('div').on('tap',function(){
console.log(this);//原生DOM
console.log($(this));// Zepto对象
})
})
</script>
zepto获取元素宽高的区别
<!-- <script src="../jquery.min.js"></script>
<script>
$(function(){
console.log($('#box').width());// 元素的内容宽
console.log($('#box').innerWidth());//元素的可视宽 content+padding
console.log($('#box').outerWidth());//元素的占位宽 content+padding+border
console.log($('#box').outerWidth(true));//元素的整个宽 content+padding+border+margin
})
</script> -->
<script src="./zepto.min.js"></script>
<script>
$(function(){
console.log($('#box').width());//content+padding+border
})
</script>
zepto offset()的区别
<!-- <script src="../jquery.min.js"></script>
<script>
$(function(){
console.log($('#box div').position());// 到有定位属性的父级
console.log($('#box div').offset());// 到文档
})
</script> -->
<script src="./zepto.min.js"></script>
<script>
$(function(){
console.log($('#box div').position());// 到有定位属性的父级
console.log($('#box div').offset());// 到文档top left 及该元素的 占位宽高
})
</script>
zepto中的touch
<script>
$(function(){
// $('div').on('tap',function(){
// console.log('tap');
// })
$('div').on('singleTap',function(){
console.log('单击');
})
$('div').on('doubleTap',function(){
console.log('双击');
})
$('div').on('longTap',function(){
console.log('长按');
})
$('div').on('swipe',function(){
console.log('滑动');
})
$('div').on('swipeLeft',function(){
console.log('左滑');
})
$('div').on('swipeRight',function(){
console.log('右滑');
})
$('div').on('swipeUp',function(){
console.log('上滑');
})
$('div').on('swipeDown',function(){
console.log('下滑');
})
})
</script>