JavaScript
1.基本认识
1.1 可以直接在标签中添加事件
123
gogogogogo
233333
1.2 script标签只能放在head或者body里面
- 一个html中可以放无数个script标签
- script标签载入有先后顺序
- 如果一个script标签已经用来引入外部的js文件了,那么在标签内写代码无用
1.3 系统弹窗 confirm prompt
let a = confirm('确认不要媳妇啦?');
console.log(a); //获得用户选择的结果, "boolean"
let b = prompt('请输入你媳妇的名字:');
console.log(b); //用户输入的结果, 取消-> null -> "object" 确定 -> string
2.数据类型
2.1 ES5、ES6定义变量的区别
ES6 定义变量,4种方式
- let
- const 常量,不可更改,初始必须赋值
- function
- class
ES5 定义变量,2种方式
- var
- function
变量命名规则:
- 严格区分大小写;
- 只能包含 字母 数字 _ $ 四大类,且不能以数字开头;
- 不能使用 关键词/保留词/已有的API;
- 见名知意。
- 函数声明时会覆盖掉同名变量
2.2 ES6的七大数据类型
- number 数字
- string 字符串
- boolean 布尔值
- undefined 未定义
- null 空 但是在浏览器上 typeof null = "object"
- symbol ES6新增的一种数据类型
- object 对象
// number
let x = 10;
// string
let x = "10";
let x = '10';
let x = `456`; //模板字符串 ES6中新的字符串定义方式
let x = "true";
// boolean
let x = true;
let x = false; //布尔值有两种,true 和 false
// undefined
let x;
let x = undefined;
const x = undefined; //const不允许初始不赋值
// symbol
let x = Symbol(123);
let y = Symbol(123); // x和y都是独一无二的 Symbol(变量)
// object
let x = [10,true,10]; //数组是对象的一种
function 和 class 定义的变量 typeof 显示"function", 其本质是object
2.3 typeof
let a = typeof NaN; //number
let b = typeof a; //b是string类型
let c; //undefined
let d = null; //typeof在检测null类型时返回object类型,其本质是null类型
let e = Symbol(123); //symbol
let f = document; //object
let g = function(){ //typeof在检测function数据会返回"function",其本质是object
};
console.log(typeof(b));
console.log(typeof c);
console.log(typeof d);
console.log(typeof e);
console.log(typeof f);
console.log(typeof g);
3. js获取dom元素节点
let a = document.getElementById("wrap"); //a就是节点对象
console.log(a); //
//ClassName不唯一,所以Elements有s
let b = document.getElementsByClassName("box");
console.log(b); //类(似)数组 HTMLCollection(3) [div.box, div.box, div.box]
console.log(b.length); // 3
console.log(b[0]); // 1
b[1].innerHTML = '阿飞';
let d = document.getElementsByName('name'); //应用在input标签
console.log(d); // NodeList [input]
3.1 html唯一标签获取
注意:打印的是标签,不是类数组节点
console.log(document.body); // body标签及其子标签
console.log(document.head); // head标签及内容
console.dir(document.title); //标题
//获取HTML,此处是引用,尽管在后面改变,但引用也会跟上
console.log(document.documentElement); //打印的是整个html页面
document.title = "阿飞";
document.documentElement.id = '狗蛋';
3.2 querySelector
let aaP = document.getElementById("wrap")
.getElementsByTagName("div")[0]
.getElementsByTagName("p"); //一层层查找,但性能仍然较querySelector好
console.log(aaP); // HTMLCollection(3) [p, p, p]
let aP = document.querySelectorAll("#wrap div p"); //All多个,参数类似css选择器
console.log(aP); // NodeList(3) [p, p, p]
/*最低支持IE8*/
let sP = document.querySelector("#wrap div p"); //只能选到第一个 打印出的就是标签
3.3 操作元素属性
w3c允许的标签属性,既是合法
合法的标签属性,直接 . 操作
- `class`比较特殊,需要使用`className`代替操作
- `style` 这个属性非常特殊,是个对象
let oDiv = document.getElementById("wrap");
//oDiv.title = '狗蛋'; 直接写
oDiv.className = 'wrap'; //属性class是保留词,这里用className
oDiv.id = 'goudan';
oDiv.innerHTML = '666
'; //虽然改了id,但oDIV仍指向这个节点对象整体,id只是其中一个属性,不能影响整体
//oDiv.innerHTML += '456'; 可以直接+=
let oGouDan = document.getElementById("goudan");
console.log(oDiv === oGouDan); //完全相等
/*
css样式
js中css属性名用驼峰法:
操作复合样式的时候,去掉 - 号,后面的第一个字母大写
*/
let oWrap = document.getElementById("wrap");
console.log(oWrap.style);
oWrap.style.height = "100px";
oWrap.style.backgroundColor = "pink"; //将background-color改为驼峰命名法,backgroundColor
oWrap.style.cssText +="width:100px;height:100px;background-color:pink"; // 也可以这样写
/ oWrap.className += " box"; / /* 操作className代替复杂的css样式设置 */
3.4 自定义标签属性
- getAttribute()
- setAttribute()
- removeAttribute() 移除属性
let oWrap = document.getElementById("wrap");
//获取自定义标签属性
console.log(oWrap.getAttribute("afei"));
//设置自定义标签属性
oWrap.setAttribute("afei","456");
oWrap.setAttribute("zhuque","123");
//移除自定义属性
oWrap.removeAttribute("afei");
//可以操作合法属性,但一般不用,没有直接.操作方便
console.log(oWrap.getAttribute("id"));
3.5 标签数据 innerHTML、innerText(火狐低版本,textContent)、value
阿飞飞 小浪浪 海文文 银时时 朱雀雀
3.6 css超级选择器
Title
4. 算术运算
4.1 隐式类型转换
- "+" 两边任意一边有字符串,那么都会进行隐式字符串转换,再进行拼接
- 布尔值和数字运算,会转换成 1 0
- 除开number string boolean之外,比如去讨论一个对象和另一个对象的加法等是没有实际意义的
let a = 10;
let b = "20";
//alert(a + b); // 弹出 "1020",结果是字符串
//alert("123" + {}); // 123[object Object]
//alert("123" + document); // 123[object HTMLDocument]
//alert("123" + undefined); // 123undefined
console.log(true + 8); // 返回9
//没意义
// console.log({}+{}); //[object Object][object Object]
// console.log([]+{}); //[object Object]
// console.log([]+[]); //
//同级运算从左到右
alert(1 + 2 + "3"); // 返回 "33"
alert("8" + 1 + 2); // 返回 "812"
// 将字符串转成数字, 前面带一个 +
console.log(+"86867");
// 数组和任何东西相加,都会转换成字符串
[1,2,3]+3 // "1,2,33"
[1,2,3]+true // "1,2,3true"
[1,2,3]+null // "1,2,3null"
[1,2,3]+undefined // "1,2,3undefined"
[1,2,3]+'' // "1,2,3"
[1,2,3]+NaN // "1,2,3NaN"
undefined+[] // "undefined"
{}+[] // "[object Object]"
- * / %都会变成数字再进行运算
出现非法运算(字符串非数字字符串进行计算)时,会出现NaN(not a number)
let a = '50p'; //非数字
let b = "40";
console.log(a - b); // NaN
console.log(a * b); // NaN
console.log(a / 20); // NaN
console.log(a % 20); // NaN
console.log(typeof(NaN)); //NaN是number类型,但不是一个数字
console.log(NaN + 10); // 返回NaN
4.2 自增和自减
let a = 10;
console.log(a++); //返回10
// let a = 10;
// let b = 5;
// console.log(a++ + b); //返回15
let a = "5";
a ++; // ++ 或 -- 会强行变数字进行计算,最终a的值也是数字
console.log(a); // 6
4.3 模板字符串
/*
单引号 或者 双引号 描述的字符串,内部不能换行
` ` 模板字符串可以
*/
let oWrap = document.getElementById("wrap");
let x = "阿飞老师有点皮"
// oWrap.innerHTML = ""+
// "- "+
// "
"+
// ""+x+""+
// "
"+
// " " +
// "
";
/* ${}可以直接引用变量,{}内是JS代码 */
oWrap.innerHTML = `
-
${x}
\$\{\}
\`\`是ES6的特点
`;
5. 运算符
5.1 赋值运算 a+=1
let a = 15;
a -= 1; //a = a - 1
a *= 2; //a = a * 2
a /= 3; //a = a / 3
a %= 4; //a = a % 4
alert(a);
5.2 比较=运算
/*
== 只比较值相等与否,不关心数据类型
=== 值与数据类型都要相等
!= 不等
!== 不全等
*/
let a = 10;
let b = "10";
console.log(a == b); //true
console.log(a === b); //false
console.log(a !== b); //true
console.log(a != b); //false
5.3 对象引用类型比较地址
/*
基础数据类型 (栈内存) 只比较值与类型
number string boolean undefined null symbol
引用数据类型 (堆内存) 比较地址
object
*/
/* a 和 b 是不同的对象,有自己的地址 */
let a = [10];
let b = [10];
console.log(a == b); //false
console.log(a === b); //false
console.log(a[0] === b[0]); //true
//console.log(false == [0]); //这样不科学的,建议 ===
5.4 字符串比较
/*
> < >= <=
*/
//字符串比较,从首位的ASCII码开始比较
let a = '3';
let b = '20';
console.log(a > b); // '3' > '2' 的ACSII码,所以返回 true
5.5 逻辑运算&& || !
/*
&& 与 //只考虑布尔值时:真真为真,其他都是假
真正的作用:遇到假就停,然后取假值,否则取后面的值
|| 或 //只考虑布尔值时:假假为假,其他都是真
真正的作用:遇到真就停,然后取真值,否则取后面的值
! 非 //只考虑布尔值时:取反
真正的作用:取数据对应布尔值的非
那些数据在被转成布尔值的时候是 false:
0 undefined null false '' "" NaN
*/
// let a = true && false;
// console.log(!a);
let a = 5 && 0;
console.log(a); //取假值,返回 number 0
let b = 8 && 9;
console.log(b); // 返回 9
console.log(NaN || 7 || 0); //返回7
console.log(!1); //返回 false
console.log(!0); //返回 true
//取一个数据对应的布尔值
console.log(!! NaN); //NaN的布尔值是false
5.6 逗号运算
/*
逗号运算符,从左到右 从上到下 运算
*/
let a = (4,5,6); //算到6后停止
console.log(a); //返回 6
5.7 运算优先级
/*
运算符优先级
. [] ()
++ -- - ~ ! delete new typeof void
* / %
+ -
< <= > >=
== != === !==
&&
||
三目
=
,
*/
// let a = 8 || 9 && 0;
// console.log(a); //返回8
let a = 10;
let b = 5;
//浏览器会惰性运算,||的左边已经确定,右边不会计算
// a = 8 || 5 && (b=6);
//console.log(a); //8
//console.log(b); //5 ,b的赋值没有计算
a = 0 || 5 && (b=6); //返回 a = 6, b = 6
console.log( 6 || (b=6) && 10 || 11); //返回6
console.log(b); //b仍未赋值
5.8 位运算(先取整再算)
/*
二进制
位运算时会将数值转换为32位整型来进行运算,
所以位运算遇到小数时,直接处理掉小数部分当成整数来运算。
*/
let a = 15;
// 00000000 00000000 00000000 00001111
// -15的二进制
// 11111111 11111111 11111111 11110000 取反码
// 11111111 11111111 11111111 11110001 反码+1
/**
* 位运算操作符:按位非`~` 、按位与`&`、按位或`|`、按位异或`^`
*左移`<<`、 无符号右移`>>>`、 有符号右移`>>`
*/
//按位取反, 满足条件 a + ~a=-1
let a = 7; // 0111
console.log(~a); // -8 ( 1..1000 结果 取反 +1 ) (0...0111 -> 0...1000)
//按位与
console.log(10 & 8); // 1010 & 1000 = 1000 => 8
//按位或
//左移
a << 2; //a * 2^2;
6. 判断和循环
6.1 三目运算
/*
哪些数据是假:
六大假 0 undefined null false "" NaN
当条件、真语句、假语句都是一条语句时,我们可以使用三目来改写if
条件 ? 真语句 :假语句
*/
4<5 ? alert('真') : alert('假');
let val = true;
//三目运算符的 优先级 低于 +
let name = "val is" + val ?"狗蛋":"大锤";
//"val is true" ? "狗蛋" : "大锤"
console.log(name);
// 多级三目,从左到右
function f(n) {
let a = n>100 ? n-100 : n>99 ? n-99 : n;
console.log(a);
}
6.2 switch
let a = '海文';
// if (a === "阿飞") {
// alert(a + "老师一般帅!");
// }else if (a === "小浪") {
// alert(a + "老师??");
// }else if (a === "海文") {
// alert(a + "斯文");
// }else if (a === "朱雀") {
// alert(a + "可爱");
// }else{
// alert(a + "喵喵喵");
// }
//switch 是全等判断
switch (a) {
case "阿飞":
alert(a + "帅!");
break;
case "小浪":
alert(a + "也帅!");
break;
case "海文":
alert(a + "斯文");
break;
case "朱雀":
alert(a + "可爱");
break;
default:
alert("喵喵喵?");
break;
}
6.3 逻辑运算符代替判断
let a = true;
function b() {
console.log(123);
}
// if (a) {
// b();
// }
a && b(); //遇到假停止,b()会运行
//先与再或,勉强可以代替三目运算
let x = 5;
let y = 6;
//console.log(x
6.4 for循环
// 2+2^2+2^3+2^4+...+2^10
let a = 1;
let sum = 0;
for(let i = 1; i <= 10; i++){
console.log("i=" + i);
a *= 2; //a = a*2
sum += a;
console.log("sum=" + sum);
}
6.5 综合案例,生成尖括号
/*
5 3
6 3
7 4
8 4
9 5
10 5
*/
let oWrap = document.getElementById("wrap");
let HTML = '';
let num = 11;
let mid = 0;
//计算oWrap的宽高
if(num & 1){ //奇数判断
mid = (num+1)/2;
}else{
mid = num/2;
}
oWrap.style.width = num*50 + 'px';
oWrap.style.height = mid*50 + 'px';
for(let i = 0; i < num; i++){
let x = i>(mid-1) ? num-i-1 : i; //箭头朝下
let y = i>(mid-1) ? i+1-mid : mid-1-i; //箭头朝上
HTML += `${i+1}`;
}
oWrap.innerHTML = HTML;
7. 循环
7.1 break vs continue
/*
break:
switch里面的break只对switch有用,不会影响到外面的for
if里面的 break ,结束上级 for 循环
continue: 该次循环结束,进入下一个循环
*/
for(let i=0;i<10;i++){
switch (i) {
case 5:
break; //作用不到for
}
console.log(i);
}
for(let i=0;i<9;i++){
if(i===5){
//continue; //执行到continue,即刻停止,进入下一个循环
break; //结束 for 循环
}
console.log(i);
}
//break只能跳出一个for,要想跳出第二层,定义一个伪变量表示for循环,break aaa;
aaa:for(let i=0;i<5;i++){
for(let j=0;j<4;j++){
if(i*j ===6){
break aaa;
}
console.log(`i===${i},j===${j}`);
}
}
7.2 while
//let在for循环内定义时,是局部变量
for(let i = 0;;)
//var在for循环内定义时,相当于全部变量
for(var i = 0;;)
let i = 0;
for(;i<4;i++){
}
console.log(i); //返回4
//全局变量下的for循环可以用while代替
var i =0;
for(;i<5;){
console.log(i);
i++;
}
var j=0;
while(j<5){
console.log(j);
j++;
}
// do while
let x = 5;
do{
console.log(x);
x++;
}while(x<5);
8. 函数
8.1 定义函数方式
/*
let a = function () {
alert(1);
}
a(); //函数加括号,自执行
*/
/*
a(); //可以放在function之前,let、var函数表达式定义的函数,不允许提前调用
function a () {
alert(1);
}
*/
/* let、var定义的函数,不允许提前调用
a();
var a = function () {
alert(1);
}
*/
let a = function b() {
alert(2);
console.log(b); //在函数里面可以获取b,此时b === a
console.log(b === a);
}
a();
//b(); //显示b()未定义,函数外面不能使用b
8.2 函数表达式
/* 使用fuction直接定义的函数不能直接加括号执行,只能通过名字再加括号执行
function a() {
alert(3);
}
a();
*/
//let定义的函数表达式,可以直接在后面加括号执行
let b=function () {
console.log(4);
}();
console.log(b); //undefined,此时b不能代表函数,b成为了函数的返回值
//匿名函数只能传参或赋值,不允许直接出现
//[function () {}] //允许
// function{} //不允许
//匿名函数加括号变成函数表达式,括号可内可外
(function () {
console.log(5);
})();
(function () {
console.log(6);
}());
//改变函数的返回值,也是函数表达式
+function(){ //一元运算符 + - 可以变为函数表达式
console.log(7);
}();
~function () { //位运算非
console.log(8);
}();
!function () { //逻辑运算非
console.log(9);
}();
8.3 参数
/*
参数
形参
实参
不定参
*/
//定义函数的时候()里面是允许写变量名字的,这些变量名字就是形参,形参只针对函数内容起作用
function a(x,y=200){
alert(x+y);
}
//函数调用的时候,()里面写的就是实参
a(7);
function f(a,b,c) {
console.log(a);
console.log(b);
console.log(c);
}
f(1,8); //从左到右进入形参,没有传入实参的,显示undefined
f(1,5,3,4); //实参多了,多的那个无效
function sum(a,b) {
console.log(a+b);
}
sum(7,8);
sum(45,1);
//求 n 个数的和,每次不一定是相同的个数,实参传入几个数,就求几个数的和
function sum(a,b,c,d) {
//不定参 它是一个类数组,存储着 所有实参
// console.log(arguments);
let s = 0;
for(let i=0,len=arguments.length;i
8.4 上下文this
console.log(this); //打印Window 是顶层属性
// window.alert(4);
// alert(a); //未定义 报错
// alert(requestAnimationFrame);
//不存在即报错
if(window.requestAnimationFrame){ //直接判断时,如果不支持,直接报错,不能进行判断,此时最好用类属性判断
console.log(requestAnimationFrame);
}
/* 函数声明,默认位于window对象内
函数(声明式or表达式一样)自执行,this指向window
*/
function a() {
console.log(this === window);
}
console.log(a === window.a); // 相等
a();
//let定义的函数不挂载window内,var定义的函数在window内
let b = function () {
console.log(this); //this都是指向window
}
console.log(b === window.b);
b();
/*
对象内的this,找 爸爸 所在的对象
*/
let afei = {
name:'阿飞',
x : function () {
console.log(this);
}
}
afei.x(); //对象方法自执行。this指向对象
let zhuque = {
xx:{
name:"朱雀的xx",
a:function () {
console.log(this === zhuque.xx);
}
}
}
zhuque.xx.a(); // 打印 父级的对象
8.5 每个函数都有返回值,默认 return undefined
//函数运行到return即停止,return后面的不执行
function a() {
alert(1);
return 2;
alert(3);
}
console.log(a());
8.6 ES6{}就是一个作用域
let关键词定义的变量,起作用的范围就是包含这个变量最近的{}
var关键词,只有在function内定义的变量,才是局部变量,while、if、for内定义的都是全局变量
同名函数会被覆盖
function a() {
alert(2);
}
function a(x,y) { //覆盖上一个定义
alert(x+y);
}
a();
8.7 获取元素的动态方法
动态有三个,意思是存储节点的变量会随着页面的改变实时改变,少了或者多了
- getElementsByClassName()
- getElementsByTagName()
- getElementsByName()
静态有以下,获取后,选择器被改也指向原对象
- querySelectorAll
- getElementById
9.作用域与解析顺序
9.1 var、function在全局作用域定义的变量默认是window对象的属性
//script标签是最大的作用域,也是全局作用域
//如果var、function在全局作用域里面定义变量。相当于给window添加了属性
var b = 10;
console.log(window.b,this); //window的属性
//ES5定义变量的关键词 var funtion
//作用域是往上离变量最近的函数
function a() {
var g = 10; // var在function内定义的才是局部作用域
console.log(g,this.b,this); //函数自执行this指向window
}
a();
//任意作用域里面,如果不加var直接产生了没有定义过的变量,那么这个变量相当于window的属性
//但是实际开发不允许这样写
function aa() {
bb = "bb"; // 赋值产生变量才行,如果直接使用则会报错
}
aa();
console.log(bb);
//面试题
function f() {
var x=y=5;
console.log(x); //x是局部的5
}
f();
console.log(y); //y未声明,因此算是window的属性,y=5
//console.log(x); //因为x是局部变量,外部访问不到,故报错
9.2 作用域链
//作用域链,操作变量时,一层层的作用域查找变量声明的地方,
//如果没有找到,调用变量会报错
//如果是赋值,在非严格模式下,变量成为windows的属性
var x=10;
function a() {
x=15; //本作用域找不到,去父级作用域找,找到后并赋值
var y=5; //局部作用域
return x+y;
}
console.log(a());
console.log(x); //全局变量被修改了,因此是15
9.3 es5解析顺序
var、function解析顺序
第一步:定义
找出当前作用域里面所有的var和function定义的变量名,不赋值,赋值是执行
此时function定义的函数,是个完整的函数,所以函数定义可以在函数执行的前后任意位置
第二步:执行
从上到下执行
alert(x); // 返回不是报错,是undefined,变量已有,但未赋值
var x=10;
//let x=10; // 报错
/*
1.定义
var x;
2.执行
alert(x); //undefined
x=10;
*/
alert(b);
function b() {
}
/*
1.定义
function b(){}
2.执行
alert(b);
*/
9.4 变量重名与覆盖
/*
定义过程中,多个var声明同一个变量,我们只需要留一个
多个函数声明重名,只留最后一个函数
var和function重名,无论先后,只留function
*/
function v() {
alert(5);
}
function v() { // 被打印
alert(10);
}
var v;
console.log(v);
9.5 闭包
函数执行每次都会产生一个新的作用域 (父级也是新的) ,彼此不相干
/*
JS自带变量回收机制,只有全局变量不会被回收,除非网页关闭;
闭包:一个使用了外部函数的参数或者变量的函数(作用域嵌套作用域,ES5只有函数能产生作用域)
*/
function a() {
var x=10;
function b() {
x++;
console.log(x,this);
}
return b;
}
//函数执行每次都会产生新的作用域,
var c=a(); //c指向函数体内的函数b,局部变量x只在a()时产生了一次,所以不会回收
//alert(c); c是函数
//c()每次执行使用的都是同一个父级作用域下的变量x
c(); //11
c(); //12
c(); //13
c(); //14
//a()每次执行后返回的都是新的作用域,使用的变量x是新的,
a()(); //11
a()(); //11
a()(); //11
闭包的作用之一,闭包避免局部变量被回收
aaaaaaaaaaa
bbbbbbbbbbb
cccccccccc
dddddddddd
eeeeeeeeee
练习
fn()();
var a = 0;
function fn(){
alert(a);
var a = 3;
function c(){
alert(a)
}
return c;
}
/*
1.定义
var a;
function fn(){}
2.执行
fn() ===> 新作用域
1.定义
var a;
function c(){}
2.执行
alert(a) undefined
a=3
return c;
fn()() ===>新作用域
alert(a),a从父级找,弹出3
*/
var a = 5;
function fn(){
var a = 10;
alert(a);
function b(){
a ++;
alert(a);
}
return b;
}
var c = fn();
c();
fn()();
c();
/*
10
11
10
11
12
*/
9.6 function属于对象类型,相等判断时是比较地址
console.log(5 === 5);
console.log([] === []); //引用,需要比地址,false
var h = function () {};
var l = function () {};
console.log(h === l); //false
function a() {
return function () {};
}
var b = a();
var c = a();
console.log(b ===c); //false
9.7 ES6的作用域
只要是在作用域里面let过的变量,那就不允许提前使用
/*
ES6定义变量
let const function class
let 和 const没有预解析,不同于var
先对定义function,进行解析
*/
alert(a); //报错
let a = 10;
let a = 20;
function b() {
//从上到下读
//暂时性死区,只要是在作用域里面let过的变量,那就不允许提前使用
alert(a);
let a = 30; //死区了,报错
}
b();
//var的作用域只认函数
if(false){
var a=10;
}
console.log(a); //undefined
//let的作用域是大括号
if(true){
let a=1;
}
console.log(a); //无法访问局部作用域
//for的小括号()是{}的父级作用域,但var不认这是作用域
const g = 10; //不允许重新赋值的常量
const a = []; //对象不能被重新赋值
a[0] = 10; //但允许改变其内容
console.log(a);
10. call apply bind
10.1 函数内的this
function a() {
console.log(this);
}
a();
/*
普通模式下, 自执行this指向window,
严格模式下, this指向undefined
被动模式下,this指向触发事件的对象
*/
document.onclick = a;
10.2 call apply
/* call()内第一个参数是函数内this的指向,后面跟的是实参,调用后会执行 */
function a(x,y) {
console.log(x);
console.log(y);
console.log(this);
}
a(8,9); //自执行
//a.call(); //call()不加参数与自执行a()效果一样
a.call(document,8,9); //this指向document
/* apply(),与call()类似,但是只有两个参数,第二个是传参的数组 */
a.apply(document,[8,9]); //this指向document
//多个参数要用数组的形式传入
10.3 bind
bind之后相当于生成一个新的函数,还未执行
/* bind不能执行 */
function a(x,y) {
console.log(x);
console.log(y);
console.log(this);
}
//a.bind(document); 这样直接写是没有效果的,只是相当于生成了一个新的函数,将this绑定给document
function b(x) {
x();
}
b( a.bind(document) ); //bind后生成了有this新指向的函数,bind是定义函数,不能直接执行,需要手动执行
a.bind(document)(10,20); //新的函数内的this指向 document
a.bind(10)(0,1); //新的函数内this指向number 10
//bind定义this指向
document.onclick = function (x,y) {
console.log(x);
console.log(y);
console.log(this);
}.bind({name:'阿飞'},200,250); //这里类似于call传参,bind产生新函数
10.4 H5新API classList
oWrap.classList.[attr] attr = add、remove、toggle
let aDiv = document.querySelectorAll("#wrap .title"),
aList = document.querySelectorAll("#wrap .friend .list"),
len=aDiv.length;
for(let i=0;i
11. ES6的解构赋值
// ES6 定义变量的解构赋值
let a = 10,
b = 20,
c = 30;
//结构模式对应,赋值效果同上
let [a,b,c] = [10,20,30];
//多了 显示 undefined
let [a,b,c,d] = [20,30,41]; // d = undefined
//不用let的变量赋值语句,变量默认是window的属性
[a,b] = [20,30,41];
//变种写法
function fn() {
let x=[];
for(let i =0;i<5;i++){
x[i]=i*i;
}
return x;
}
let [a,b,c,d,e] = fn();
//对象的解构赋值,属性是用来对应的,只有变量定义了
let {a:x,b:y} = {a:10,b:20};
console.log(x);
console.log(a); // 报错,属性不是定义的
let {x:x,y:y} = {a:10,b:20,y:30};
console.log(x); //找不到右边对象的x属性,所以变量x显示未定义
console.log(y); //属性对应才能赋值 y=30
//注,属性和变量相同时,可以只写一个
let {x,y} = {x:10,y:30};
console.log(x,y);
//ES6新增简写规则
let a = 10,
b = 20,
c = {
a,
b
};
/*属性名和变量名相同,可以简写,对象c的定义同下
c = {
a:a,
b:b
}
*/
console.log(c);
11.1 深层解构赋值
let [a,[b,c],d] = [1,[2,3],4];
console.log(a,b,c,d);
let [a,b,{x,y}] = [1,2,{x:10,y:20}];
console.log(a,b,x,y);
11.2 解构赋值时默认值写法
只有右边**严格等于undefined**时取默认值
不允许前面的默认值用后面的变量值
/*使用解构赋值,取默认值的方法*/
function fn(data) {
let a = data.a;
let b = data.b;
let c = data.c || 100; // 要确保传入的值不是假,否则走默认值,这种不严格
// 必须严格的走 全等undefined,再添加默认值
if(c === undefined){
c = 100;
}
}
fn({a:10,b:20});
//ES6的默认值写法,左边写一个等于,只有右边严格等于undefined时取默认值
function fn(data) {
let {a:a=1,b:b=2,c:c=100} = data; //左边严格上说不能认为是对象,只有右边是对象
console.log(a,b,c); // c = null
}
fn({a:10,b:20,c:null}); // 这里 null===undefined 不成立,
//数组默认值写法
let [d,e,f=90] = [7,8];
console.log(d,e,f);
//默认值是表达式时,如果不需要默认值,则默认值无法执行
function f1() {
console.log("12");
}
let [x = f1()] = [1]; // x=1, f1未执行
let [y = f1()] = [undefined]; // y=undefined, 是f1执行后的返回值
//不允许前面的默认值用后面的变量值
let [m=n,n]=[undefined,1];
console.log(m,n); //报错
12. 字符串方法
12.1 基本数据类型包装对象无意义
undefined null 等不能进行点操作,会报错的
//基础数据类型虽然可以点操作,但没有意义,拿不到包装对象;
//点操作本质上是针对数据的包装对象进行操作,每一次的包装对象都是新产生的对象,不能确定
//undefined null 等不能进行点操作,会报错的
let a='阿飞';
a.index = 20; //不能给字符串添加自定义属性,不会报错,显示undefined,这是操作的a的包装对象,用了即消失,存不下来
console.log(a,a.index); //第二次的点操作是操作的全新的包装对象,用后即消失
/*
let b={};
b.index = 20; //对象可以添加自定义属性
console.log(b);
*/
let a = new String("阿飞"); //这里的a是字符串对象
a.index = 20; //a的包装对象是 new String(),可以添加自定义属性
console.log(a+"朱雀",a.index);
12.2 str.charAt() 取出字符串中的第几位字符,不能赋值
let a = '阿飞';
//console.log(new String(a)); //可以打印包装对象属性为String的对象
//针对a的包装对象的charAt
console.log(a.charAt(1)); //取出字符串中的第几位字符
console.log(a[0]); // a的包装对象有a的内容,对象访问时可以的,但是IE6,7不支持,最好用charAt
//包装对象不能赋值,没有意义;使用即消失,存不了
a[0]="5";
console.log(a[0]);
12.3 str.charCodeAt() 获取ASCII编码
/*
charCodeAt()
调用第几个字符的编码,
String.fromCharCode()
与之相反,从ASCII码到字符
*/
let a = "阿A飞";
let b = `阿
飞`;
console.log(a.charCodeAt(1)); // 65
console.log(b.charCodeAt(1)); //换行码是 10
console.log(String.fromCharCode(39134)); // 飞
//加密,利用ASCII码
let c = "小卑鄙我爱你";
let d = "";
for(let i=0,len=c.length;i
12.4 str.substring(x,y) 字符串截取一段[x,y),xy大小无所谓,y默认为len
/*substring(x,y) 从第x位到第y位截取,x要,y不要*/
// slice可以倒着截取
let a="abc阿飞789456";
let b = a.substring(3,5); //包含3,不包含5
console.log(b); //阿飞
let bb=a.substring(5,3); //没有前后要求,会自动调整
console.log(bb); //阿飞
let c = a.substring(3); //从3到结尾
console.log(c); //阿飞789456
let d = a.substring(-2,3); //没有负值,会认为0
console.log(d); // abc
let e = a.slice(-5,-2); //负值表示从后开始数,倒着数,要满足先后顺序
console.log(e); // 894
12.5 大小写转换toLocaleUpperCase
//主要针对英文字母大小写
/*
toLocaleUpperCase()
*/
let a = "abc";
let b = a.toLocaleUpperCase();
console.log(b);
console.log(b.toLocaleLowerCase());
12.6 indexof()返回坐标,默认-1
/*
找位置,返回num
*/
let a = "我觉得阿飞老师是最皮的";
console.log(a.indexOf("阿飞"));
//指定位置开始找,后面加一个参数
console.log(a.indexOf("老师",3));
//找不到返回 -1
12.7 split(",")切割返回数组,join(",")拼接成字符串
// 使用split()进行切割,返回一个包含分开特定字符前后元素的数组
let a = "阿飞,朱雀,心艾,岚岚,丫丫,艾米";
let b = a.split(",");
console.log(b);
console.log(b.join("php"))
// let c = a.split("");
// console.log(c);
12.8 ES字符串扩展
function fn(a,b) {
console.log(arguments); // [ 0:["1,2", "阿飞", ""], 1:5 , 2:6 ]
console.log(a+b); // 1,2,阿飞,5
}
//fn(1,2);
let b=5;
let a = 6;
fn`1,2${b}阿飞${a}`;
13. 数组方法
13.1 push pop shift unshift
增加,返回数组长度,删除,返回被删的内容
/*
push
参数:任意数据
功能:直接改变原数组
返回值:返回改变后数组的长度
pop
参数:null
功能:改变原数组,删除最后一位
返回值:删除的元素
shift
功能:改变原数组,删除第一位
返回值:删除的元素
unshift
功能:改变原数组,从第一位添加
返回值:数组长度
*/
let a = ["阿飞","无虑"];
console.log(a.push("小浪","海文"));
console.log(a);
console.log(a.pop());
console.log(a);
console.log(a.shift());
console.log(a);
console.log(a.unshift("first"));
console.log(a);
//骚操作,
// pop()返回的是删除的最后一个函数,后面跟参数执行
let x = [5,function(x){alert(x)}];
x.pop()(x[0]);
13.2 a.indexOf() a.slice()
//类数组除了.length,不能执行其他api
let a = ["阿飞","无虑","朱雀"];
console.log(a.indexOf("朱雀")); //2
//数组截取
let b = a.slice(1);
console.log(b); // ["无虑", "朱雀"]
13.3 数组切割splice()
返回被切割的部分
//数组切割,单个参数时,包含前面而不含后面的
let a = ['阿飞','无虑','小浪'];
console.log(a.splice(1)); //从第1个切,切到最后 ["无虑", "小浪"]
console.log(a); // ["阿飞"]
//第二个参数表示切除几个
console.log(a.splice(1,1)); //从第1个开始切除1个 ["无虑"]
console.log(a); // ["阿飞", "小浪"]
//添加与替换
a.splice(1,1,'朱雀','心艾'); //切除一个,替换了2个 ["无虑"]
console.log(a); // ["阿飞", "朱雀", "心艾", "小浪"]
13.4 数组排序a.sort() a.reverse()
二分法排序
不加参数,默认升序, 数组被改变了,但引用地址没变,仍相等
//一般只是针对num类型数组排序,其他类型没有意义
// sort()从小到大排序,升序
// reverse() 反序,元素从后往前排,可以先升序再反序实现降序排列
// 返回值是排列完成之后的数组,
let a=[12,78,50,20,32,40,90];
a.sort();
console.log(a);
a.reverse();
console.log(a);
console.log(a.sort() === a); //改变之后还是a本身,相等
//降序
console.log(a.sort().reverse());
//JS二分法排序 a-b: 为升序 b-a: 为降序
a.sort(function (a,b) {
return a-b;
})
console.log(a);
let a = [
{name:'阿飞',age:20},
{name:'朱雀',age:30},
{name:'丫丫',age:18},
{name:'心艾',age:80},
{name:'岚岚',age:22},
{name:'发发',age:22},
{name:'艾米',age:28}
];
//a.sort(); 无法直接对对象排序
a.sort(function (a,b) {
return b.age-a.age; //后者减前者,降序
})
console.log(a);
13.5 数组拼接数组 a.concat(b)
// concat 拼接数组
let a = [1,2,3];
let b = [4,5,6];
let c = a.concat(b); //将b拼接到a的后面
console.log(a,b); //不改变原数组
console.log(c);
13.6 数组方法 Array.isArray(a)
// 只有 Array 可以使用 isArray()方法
let a = [1];
let b = document.querySelectorAll("div");
console.log(Array.isArray(a));
console.log(Array.isArray(b)); //常用于判断类数组,其没有数组常用的方法
13.7 数组拼接字符串 a.join(",")
let a = ["阿飞",'心艾','朱雀'];
let b = a.join("<==>"); //通常将字符串数组元素拼接成一个新的长的字符串
console.log(a); //不改变原数组
console.log(b); //b是返回的长字符串 阿飞<==>心艾<==>朱雀
13.8 数组遍历 a.forEach(v,i)
//forEach 遍历数组,必须要有函数作为参数,自动执行length次,不支持函数return
/*
接收函数,该函数第一个形参代表每一位的数据,
第二个形参代表每一位的序号,
第三个形参代表原数组
*/
let a = [4,5,6,7,8,9];
let b=a.forEach(function (x,y,z) {
console.log(x,y,z);
});
console.log(b); //undefined
//与forEach效果一样
for(let i=0;i
13.9 数组遍历 a.map(cb(val,i))
//map是有返回值的数组遍历,返回一个基于原数组结构的数组
let a = [1,2,4,5];
let b = a.map(function (x,y,z) {
console.log(x,y,z);
return x*x;
});
console.log(a); //map不改变a
console.log(b); //b是基于a结构的新生数组 [1, 4, 16, 25]
**ES6 的Map对象,可用于记数**
let a = [1,2,4,5];
let c = new Map()
a.map(function (val,index) {
c.set(index,value) // 实例方法,设置 map数据
})
console.log(c); // Map对象实例 Map(4) {0 => 1, 1 => 2, 2 => 4, 3 => 5}
c.get(3); // 5 按set时的index查找
c.has(0); // true index
c.keys(); // MapIterator {0, 1, 2, 3}
c.values(); // MapIterator {1, 2, 4, 5}
[...c]; // [[0,1], [1,2], [2,4], [3,5]]
13.10 过滤 a.filter(cb(val,i))
/* 遍历
func:过滤
生成一个过滤后的数组,return true 留下,false 过滤掉
*/
let a=[10,20,5,7,89,41];
let b=a.filter(function (x,y,z) {
console.log(x,y,z);
return x>10; //将x>10的留下,新生一个数组
});
console.log(a); //不改变原数组
console.log(b); //b是过滤后的数组
13.11 ES6 ...扩展
let a = [1,2,3];
console.log(...a); //去除数组括号,拆解成单个,ES6兼容,babel可转
console.log(1,2,3); //与上等价
//param形参
function f(param) {
console.log(param); // 只有一个形参 1
}
//f(1,2,3);
f(...a);
/*
let c = (...a); //这样做是不允许的
console.log(c);
*/
...数组拼接
// ...数组拼接
let a = [1,2,4];
let b = [5,6,7];
//let c = a.concat(b);
let c = [...a,...b];
console.log(c);
...解构赋值
//b是数组,拆开后赋值, ...b只能放在后面,表示接受全部
let [a,...b]=[1,2,3,4];
console.log(a); // 1
console.log(b); // [2, 3, 4]
...与iterator接口
//常见的Iterator遍历器接口
/ Array String nodelist arguments /
// Nodelist是节点对象集合
function fn(a,b,c) {
console.log(a,b,c);
}
fn("753"); // 753 undefined undefined
fn(..."753"); // 7 5 3
...与NodeList
let aP = document.getElementsByTagName("p");
// 类数组不能用数组的遍历
// aP.forEach(function (val,index) {
// });
//ES5就有办法将 aP 先搞成数组,之后再使用forEach
//slice不传参数就不切割,数组切割,方法slice使用call改变切割对象执行,返回一个真数组
let x = [].slice.call(aP); //生成一个新数组
console.log(x);
x.forEach(function (node,index) {
node.onclick = function () {
alert(index);
}
})
//ES5 类数组=>真数组遍历遍历
[].slice.call(aP).forEach(function (node,index) {
node.onclick = function () {
alert(index);
}
});
//ES6 , ...将Nodelist拆了,加上[]成为真数组
console.log([...aP]);
[...aP].forEach(function (n,i) {
n.onclick = function () {
alert(i);
}
});
...与function
//任何拆解都要放在最后面
function fn(a,...b) {
console.log(a);
console.log(b);
}
fn(4,5,6);
function fn(...argu) {
console.log(argu); //ES6的...可以直接代替arguments
}
fn(7,8,9);
14. 数学对象
14.1 Math
- Math.pow(x,y)表示x的y次方
- Math.trunc(-5.999991) 去小数点取整 -5
/*
Math 对象
属性:
方法:
*/
//小数表示方式: 0表示正负 10表示小数点的位置为2 10.1010的整数部分为2,小数部分是1010/2^4, 10/16
//var a = 0 10 10.1010; //表示 2.625
/*
Math.abs()
1.传入的值是正确的,返回一个新的绝对值结果,字面量赋值
2.传入的值是数字字符串,会取value值取绝对值
3.单个数字元素的数组也会取值,多个数字元素也是NaN
4.传入的值其他类型,返回NaN,表示not a number
*/
console.log(Math.abs(["-888"])); // 888
//Math.pow(x,y)表示x的y次方
console.log(Math.pow(2,10)); // 1024
//开方,y小于1
console.log(Math.pow(256,1/2)); // 16
//过气的开二次方
console.log(Math.sqrt(256)); // 16
//取整,floor接地气,往小了取整,正负一样
console.log(Math.floor(2.5),Math.floor(-2.01)); //2 -3
//向上取整
console.log(Math.ceil(2.5),Math.ceil(-2.9)); //3 -2
//四舍五入取整
console.log(Math.round(4.49),Math.round(-4.6)); //4 -5
//去小数点取整
console.log(Math.trunc(-5.999991)); // -5
14.2 三角函数
/*
圆周 2PI 360deg
PI/6 30deg
PI/3 60deg
sin 正弦 对/斜
cos 余弦 邻/斜
tan 正切 对/邻
反三角
arcsin
*/
console.log(Math.sin(Math.PI/6),Math.cos(Math.PI/3),Math.tan(Math.PI/4)); //结果有小数,不精确
console.log(Math.asin(0.5),Math.PI/6);
14.3 随机数 Math.random()
/*
Math.random() 返回一个[0,1)的数
*/
//console.log(Math.random(),Math.round(Math.random()*10));
// 生成一个n到m的随机数,m取不到
const rdm = function(n=0,m=n+1){
return Math.floor((m-n)*Math.random()+n);
}
console.log(rdm(1,7));
14.4 parseInt() parseFloat()
/*
非数学对象
parseInt(a,b)
a 需要转换的数值,隐式转换成字符串
b 进制(2,36) 10+26
*/
console.log(parseInt("123abc")); //返回字符串中的整数部分,遇到NaN停止 返回123
//第二个可选参数是进制
console.log(parseInt("ff",16)); //按16进制解析,结果是10进制255
console.log(parseInt("0xa")); // 10
/*
parseFloat()返回带小数点的
在底层parseFloat会先判断传入的参数类型,转换成字符串;
如果传入对象,会默认调用对象的toString()方法
*/
console.log(parseFloat("12.3254a"));
console.log({}.toString()); // 打印 "[object Object]"
//ES6次方简写
console.log(3**2); //表示3的平方
14.5 立方根cbrt,e的幂exp, 单精度浮点 fround
// cbrt是取立方根结果,类似 Math.pow(27,1/3)
console.log(Math.cbrt(27),Math.pow(27,1/3)); //3 3
// exp是自然对数e的幂函数,e^ln2 = 2;
console.log(Math.exp(Math.LN2),Math.exp(Math.LN10)); //2 10
// 转成最近的单精度浮点数的数字
console.log(Math.fround(100.1));
15. 对象方法
15.1 对象遍历 for in
let a={
name:'阿飞',
'age':18,
marry:true,
handsome:true
}
//for in循环,遍历对象,也可以是数组
for(let key in a){
console.log(key,":",a[key]);
}
15.2 对象的增删改查
//对象的属性是无序的,一般按照字母先后顺序展示
let a={
name:'阿飞',
age:18,
marry:true
}
console.log(a); //这里a是引用,后面改了,这边也能相应
//增
a.GF = ['朱雀','丫丫','岚岚','茜茜'];
//改
a.age = 21;
//删除
delete a.marry;
//查找,是否存在
console.log('age' in a);
15.3 json JSON.stringify() JSON.parse()
//json 是一个格式非常标准长得像对象的字符串
//通用字符串,基本上所有语言都能识别的字符串格式
//let a = '{"name":"阿飞","age":18,"marry":true}';
let a={
'name':'阿飞',
age:18,
marry:true
};
//将一个对象转为JSON格式 JSON.stringify() 反序列化
let b=JSON.stringify(a)
console.log(b);
//将JSON序列化, JSON.parse() 解析成对象
let c = '{"a":10,"b":"狗蛋","c":true}';
//必须是标准严格的JSON格式才能解析,里面必须用双引号包起来""
console.log(JSON.parse(c));
15.4 es6的默认值
let [a,b=10]=[5]; // a=5 b=10
let {x:hh,y:tt=20} = {x:11}; // hh=11 tt=20
// function fn([a,b]) {
// console.log(a,b,arguments);
// }
// fn([5]);
function fn({a=10,b=100}) {
console.log(a,b,arguments);
};
//fn({a:5});
//fn({a,b});
fn({}); // 10 100
//无实参取形参的默认值{x,y},有实参对应实参的默认值{x:10,y:30}
function ffn({x,y} = {x:10,y:30}) {
console.log(x,y);
}
ffn(); //10 30
ffn({}); //un un
15.5 箭头函数
/*
ES6 箭头函数
() =>
*/
/* 形参 返回值 */
let fn = v => v;
//ES5写法如下
var fn = function (v) {
return v;
}
/* 加法写法 */
var fn = function (a,b) {
return a+b;
}
let fn = (a,b) => {a+b};
/* 函数内容较多 */
var fn=function (a,b) {
let c = a+2;
let d = b-3;
return(c+d);
}
let fn = (a,b)=>{
let c = a+2;
let d = b-3;
return(c+d);
}
/* 如果返回对象时,需要再加上() */
var fn = function () {
return {a:10,b:20};
}
let fn = () => ({a:10,b:20})
/*
document.onclick = function () {
console.log(this);
}
*/
//通常用在回调函数内,方便使用
let arr=[1,2,3];
arr.forEach((value,key)=>{
console.log(value);
});
let b = arr.map(v=>v*v); //结果平方返回
console.log(b);
16.定时器
16.1 setTimeout(cb,T)
/*
setTimeout 一次执行定时器
param1:回调函数,或者是字符串包裹的js脚本,或者是引号包裹的全局作用域内的函数自执行
param2:数字(毫秒单位)
*/
setTimeout(function () {
alert("timeout!");
},1000);
let fn = function () {
alert(1);
return function () {
alert(3);
}
};
setTimeout(fn(),1000); //不能是返回值,第一个参数是函数
let str = "let a=10;alert(a);"; //可以接收字符串参数,当成JS代码来读
setTimeout(str,2000);
let fn = function () { // 如果fn不在全局作用域内,则 "fn()"找不到将报错
alert(4);
};
setTimeout("fn()",1500); //默认在全局中执行引号的内容,作用域在全局
16.2 setInterval(cb,T)
/*
setInterval 循环定时
*/
let num=0;
let fn = function () {
console.log(++num);
}
setInterval(fn,1000/60); //最小时间间隔最多是60次每秒,
16.3 定时器队列
主程序执行完之后才执行定时器队列
//读到setTimeout时将定时器放入队列中,主程序执行完之后才执行队列
//所以先弹出3,后弹出4
setTimeout(function () { //进入队列后执行
alert(4);
},0);
!function fn() { //先执行
alert(3);
}();
16.4 参数
回调函数带参时,放在定时器第二个参数之后
//定时器的函数有参数时,直接放在第二个参数之后
(function () {
function fn(a,b) {
console.log(a+b);
}
//setInterval(fn(2,7),1000); //这样会直接执行
/*
setInterval('fn(2,7)',1000); //双引号内的内容默认丢在全局中执行,全局中找不到fn,报错
window.fn = fn; //将局部fn赋值到window
*/
setInterval(fn,1000,25,14); //参数接着放
})();
16.5 返回值
/*
返回值是按定时器出现顺序从1号开始的编号,作用是用来清除定时器的
编号不区分作用域
*/
let x = setTimeout(function(){alert(3);},50000);
let y = setTimeout(function(){alert(4);},60000);
let z = setTimeout(function(){alert(5);},70000);
let w = setInterval(function(){alert(6);},80000);
let v = setInterval(function(){alert(7);},90000);
console.log(x,y,z,w,v); // 1 2 3 4 5
16.6 清除定时器
clearInterval(t)
clearTimeout(t)
let x = setTimeout(function(){console.log("a")},2000); // 1
let y = setTimeout(function(){console.log("b")},2000); // 2
console.log(x,y);
clearTimeout(y); //清除编号为2的定时器
// 定时器的队列编号跟作用域没关系,按出现顺序编号
(function () {
let x = setTimeout(function(){console.log("a")},2000); // 3
let y = setTimeout(function(){console.log("b")},2000); // 4
console.log(x,y);
})();
16.7 requestAnimationFrame(cb)
canselAnimationFrame()
/*
H5出的新的API
requestAnimationFrame() 不需要第二个参数,间隔是浏览器的刷新频率,单次执行
主要是让动画很流畅,浏览器准备好就刷新
CSS3关于动画的API底层都是它
取消
canselAnimationFrame()
*/
let oW = document.getElementById("wrap");
let start=0;
function m(){
start += 2;
oW.style.left = start+'px';
requestAnimationFrame(m);
}
requestAnimationFrame(m);
// 兼容
window.requestAnimationFrame = window.requestAnimationFrame || function (fn) {
setTimeout(fn,1000/60);
};
window.cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
16.8 案例,自动无缝轮播图
关键点: oImg.style.transitionDuration = 0+'s';
Title
-
-
-
-
-
-
-
<
>
17. 时间API
17.1 Date类
/*Date类
new Date()
本地此时此刻的日期对象/时间戳
*/
let d = new Date(); //获取的是对象
console.dir(d);
console.log(d.getTime()); // 时间戳
let t = new Date(d.getTime());
console.log(t);
//以下API返回数字 number
console.log(d.getFullYear()); //得到 年
console.log(d.getMonth()+1); //得到 月(从0开始计数,应该+1返回)
console.log(d.getDate()); //日
console.log(d.getHours()); //时
console.log(d.getUTCHours()); //0时区 UTC
console.log(d.getMinutes()); //分
console.log(d.getSeconds()); //秒
console.log(d.getDay()); //星期 星期日是0
console.log("====================");
console.log(d.toUTCString());
let x = new Date(); //日期对象可以做减法,会自动调用getTime进行相减
//定时器都不是 精准的计时
setInterval(function () {
let y=new Date();
console.log(y-x);
x=y;
},50); //周期很小,则误差较大
17.2 设置时间戳
//无参是获取,有参是设置
let x=new Date(2018,8-1,8,1,1,1); //月份从0开始的,所以设置8月应输入7
let x=new Date(2018); //只有一个参数时,会被认为是毫秒时间戳,从1970年开始加
let x=new Date(2018,5-1); //默认1日,0时0分0秒
console.log(x);
let a = new Date().getTime();
console.log(new Date(a-3600000)); //打印一个小时前的时间
17.3 网页倒计时跳转
404 页面未找到~~
8秒后,返回 主页
17.4 新年倒计时
(function () {
let oW = document.getElementById("wrap");
let x = new Date(2020,2-1,24); //过年时间
function fn(){
let d = x - new Date(); //差了多少秒
let DD = Math.floor(d/1000/60/60/24); //天
let HH = Math.floor(d/1000/60/60%24);
let MM = Math.floor(d/1000/60%60);
let SS = Math.floor(d/1000%60);
if(DD<10) DD = '0'+DD;
if(HH<10) HH = '0'+HH;
if(MM<10) MM = '0'+MM;
if(SS<10) SS = '0'+SS;
oW.innerHTML = `距离过年还有 ${DD} 天 ${HH} 小时 ${MM} 分 ${SS} 秒;`;
};
fn();
setInterval(fn,1000);
})();
18. 运动框架
18.1 基础的移动
Title
18.2 封装好的运动框架
Title
'use strict';
/*
* 运动框架
* param:
* ele - object 必须 表示要进行运动的节点
* attr - string 必须 表示要改变的css属性
* target - number 必须 表示属性的终点值
* step - number 选填 表示运动速度的正值,默认5
*return:
*
*/
window.Move = function () {
//兼容定时器
window.requestAnimationFrame = window.requestAnimationFrame || function (fn) {
setTimeout(fn, 1000 / 60);
};
window.cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
//框架函数
return function Move(ele, attr, target) {
var step = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 5;
//ele.style.marginLeft 只能获取行内样式
//console.log(getComputedStyle(ele)); //原生JS,存储着节点对象全部的样式
//获取存储着ele展示样式的对象
var cssObj = ele.currentStyle || getComputedStyle(ele); //解决兼容性问题IE8用currentStyle
//初始的值
var sVal = parseFloat(cssObj[attr]); //去掉单位,变成数字
//兼容IE的opacity
if(attr === "opacity" && isNaN(sVal))sVal=1;
//考虑初始值与目标值大小的问题
var bool = sVal>target;
if(sVal > target){
step = -Math.abs(step); //负值
}else if (sVal < target){
step = Math.abs(step); //正值
}else{
return;
}
function f() {
sVal += step; // + -step
if (bool?sVal<=target:sVal>=target) {
sVal = target;
}else {
requestAnimationFrame(f);
}
if(attr === 'opacity'){
ele.style[attr] = sVal;
ele.style.filter = "alpha(opacity="+100*sVal+")"; // IE浏览器兼容
}else if(attr === 'zIndex'){
ele.style[attr] = sVal; //不加单位
}else{
ele.style[attr] = sVal + 'px'; //加单位
}
}
requestAnimationFrame(f);
};
}();
19. DOM
19.1 节点nodeType nodeName nodeValue
/*
元素节点的nodeType是 1 nodeName是 大写的标签名 nodeValue=null
元素属性的nodeType是 2 nodeName是 属性名 nodeValue=属性值
文本节点的nodeType是 3 nodeName是 #Text nodeValue=文本内容
注释节点的nodeType是 8 nodeName是 #comment nodeValue=注释内容
*/
let oW = document.getElementById("wrap"),
oC = document.getElementsByClassName("content")[0];
console.dir(oW);
console.log(oW.nodeType); //1 元素节点
console.log(oW.nodeName); //DIV
console.log(oW.childNodes); //子节点,包含所有节点类型
console.log(oW.attributes[2].nodeType); // 2
// console.log(typeof oC.childNodes[0].nodeValue);
oW.attributes[2].nodeValue = '朱雀'; //不建议这样修改,应该坐标是不确定的
console.log(oW.attributes[2]); // afei='朱雀'
19.2 子节点 childNodes children
19.3 插入节点createElement
- createElement 创建元素节点
- createTextNode 创建文本节点
- appendChild 创建的是子节点
- insertBefore(A,B) 创建子节点,A元素节点放在B元素节点之前
19.4 修改节点位置
阿飞
朱雀
19.5 删除节点 removeChild()
555
666
19.6 获取节点
- firstChild 第一个子节点,一般获取的都是文本节点 ->换行符
- firstElementChild 第一个元素子节点
- nextSibling 下一个兄弟节点
- nextElementSibling 下一个兄弟元素节点
- previousElementSibling 上一个兄弟元素节点
11
22
33
- parentNode 父亲节点
- offsetParent 定位父级,离得最近的拥有定位的父级,都没有时就是body
Title
4545454
19.7 克隆节点 oP.cloneNode()
节点的事件不被克隆
- oP.cloneNode() 默认不复制内容
- oP.cloneNode(true) 包括内容全部复制,但事件不会复制
745545
444
19.8 节点替换 replaceChild(A,B) , A将B替换掉
123
456
19.9 节点片段 document.createDocumentFragment()
(function () {
let oW = document.getElementById("wrap");
//生成10个小球
(function () {
//节点片段,暂时存放节点的对象
let oF = document.createDocumentFragment();
//生成十个小球,一次性append进oW内,省的渲染多次
for(let i=0;i<10;i++){
let oP = document.createElement("p");
oF.appendChild(oP);
}
oW.appendChild(oF);
})();
//运动
(function () {
let aP = [...oW.children];
let MaxL,MaxT;
window.onresize = (function r(){
MaxL = window.innerWidth - 100;
MaxT = window.innerHeight - 100;
return r;
})();
//随机初始速度
let speedArr = [];
aP.forEach((ele,index)=>{
speedArr[index] = {
stepX : Math.floor(Math.random()*12+4),
stepY : Math.floor(Math.random()*12+4)
};
});
//随机颜色
function changeColor(ele) {
let [r,g,b] = [
Math.floor(Math.random()*256),
Math.floor(Math.random()*256),
Math.floor(Math.random()*256)
];
ele.style.backgroundImage = `radial-gradient(white,rgb(${r},${g},${b}))`;
}
//遍历运动
!function m(){
aP.forEach((ele,index)=>{
let left = ele.offsetLeft + speedArr[index].stepX;
let top = ele.offsetTop + speedArr[index].stepY;
if(left >= MaxL){
left = MaxL;
speedArr[index].stepX = -speedArr[index].stepX;
changeColor(ele);
}
if(left <=0){
left = 0;
speedArr[index].stepX = -speedArr[index].stepX;
changeColor(ele);
}
if(top>=MaxT){
top = MaxT;
speedArr[index].stepY = - speedArr[index].stepY;
changeColor(ele);
}
if(top<=0){
top = 0;
speedArr[index].stepY = - speedArr[index].stepY;
changeColor(ele);
}
ele.style.left = left+'px';
ele.style.top = top + 'px';
});
requestAnimationFrame(m);
}();
})();
})();
20. DOM宽高属性与事件对象
20.1 视图页面宽高,无单位
window.innerWidth
document.documentElement.clientWidth
20.2 元素宽高,无单位
- getComputedStyle(oWrap).width css样式宽度,有单位
- oWrap.clientWidth 客户端宽度 width+padding 无单位
- oWrap.offsetWidth 客户端宽度 + border
- oWrap.scrollWidth 滚动宽度,一般用在出现滚动条, = 客户端宽度
/*
number类型
clientHeight/clientWidth width+padding
offsetHeight/offsetWidth width + padding + border
scrollHeight/scrollWidth 滚动宽度,超出视图仍显示正常宽度,不管有没有超出隐藏
*/
let oWrap = document.getElementById("wrap");
console.log(getComputedStyle(oWrap).width); //获取元素css样式设置的宽度,有单位
console.log(oWrap.clientWidth); //width + padding
console.log(oWrap.offsetWidth); //width + padding + border
//scrollWidth 元素占用的宽度,生成滚动条,内容不超出时数值等于clientWidth
console.log(oWrap.scrollWidth); //如果有超出部分,正确的反映出超过之后的宽度,不管有没有加超出隐藏
20.3 定位left值offsetLeft与top值offsetTop
只有距离定位父级的左值和上值 ,没有右下
Title
8888
20.4 body的滚动高度,用document.documentElement.scrollTop
20.5 元素的滚动高,父级的scrollTop
Title
20.6 scrollTop无单位,可以赋值
20.7 getBoundingClientRect()获取边界客户端矩形,对象形式,无单位
Title
8888
20.8 oW.scrollIntoView(true) 滚动到可视区
Title
20.9 event事件对象
/*
event事件对象
事件函数执行时,第一个形参就是事件对象:存储着和该次事件相关的一些信息
IE8及以下浏览器,使用event全局变量来表示事件对象
该对象里面比较重要的一些属性
clientX/clientY 事件触发时,鼠标距离可视区的距离
pageX/pageY 鼠标距离文档的位置(IE8 不兼容)
*/
//IE的事件函数没有形参
//兼容
document.onclick = function (ev) {
ev = ev || window.event; // IE的Event是全局变量
console.log(ev);
}
20.10 鼠标事件 onmousedown onmousemove onmouseup
document.onmousedown = function () {
console.log("down");
document.onmousemove = function () {
console.log("move");
}
}
document.onmouseup = function () {
console.log("up");
document.onmousemove = null; //默认属性是null
}
20.11 案例:可拖拽的盒子
Title
20.12 案例:十球发射
Title
21. DOM事件
21.1 事件冒泡
冒泡触发顺序:从子元素开始到窗口
- event.stopPropagation() 主流浏览器阻止冒泡:
- event.cancelBubble = true; IE阻止冒泡
box1
box2
21.2 事件监听
- attachEvent("onclick",cb) IE8
- detachEvent(事件类型,回调方法);
- addEventListener(事件类型,回调方法,捕获|冒泡) 主流浏览器
- removeEventListener(事件类型,回调方法,捕获|冒泡);
捕获与冒泡顺序相反
var oW = document.getElementById("wrap");
//DOM 0级事件, 相同名字的事件被覆盖,只能监听一个事件
oW.onclick = function () {
console.log(1); //被覆盖
};
oW.onclick = function () {
console.log(2);
};
/*
事件监听(默认事件冒泡)
用到事件的地方最好就是使用 DOM2级来监听
监听事件
主流浏览器 事件类型 "click"
ele.addEventListener(事件类型,回调方法,捕获|冒泡)
1.this指向节点本身
2.捕获与冒泡
默认是false 冒泡事件
true为捕获,与冒泡的顺序相反,从最大父级到子级开始(也能使用阻止冒泡的方式)
ie浏览 ie8 事件类型 "onclick"
oW.attachEvent(事件类型,回调方法)
1.this不再指向节点本身,指向window
ie8没有事件捕获,默认是冒泡事件
移除事件
主流浏览器
ele.removeEventListener(事件类型,回调方法,捕获|冒泡);
IE8
ele.detachEvent(事件类型,回调方法);
*/
//事件监听DOM 2级事件
//IE8
oW.attachEvent("onclick",function (e) {
e = e||window.event;
console.log(this); //this 不再指向监听事件的节点本身
console.log(e);
});
/* 主流浏览器 */
oW.addEventListener("click",function () {
console.log("我又监听了一次点击事件,理解一下DOM 2级事件");
})
var callback = function () {
console.log(1);
};
oW.addEventListener("click",callback);
//文档双击,注销事件
//该事件必须事先用变量保存,removeEventListener的参数必须与添加事件监听的参数一样,才能移除
document.ondblclick = function () {
oW.removeEventListener('click',callback);
}
21.3 事件默认行为
- oncontextmenu 默认行为指右键可选事件
- return false; dom0级阻止默认行为
- event.preventDefault(); 阻止默认行为
- event.returnValue = false; IE8阻止默认行为
默认行为
默认行为
默认行为
默认行为
默认行为
默认行为
默认行为
默认行为
默认行为
默认行为
默认行为
默认行为
21.4 滚轮事件
- mousewheel 滚轮事件 event.wheelDelta 滚动的幅度 下负上正 120 谷歌+ie
- DOMMouseScroll 火狐的滚轮事件 event.detail 滚轮的幅度 上负 3
let oW = document.getElementById("wrap");
/*
谷歌以及ie
event.wheelDelta 滚动的幅度
-120 下滚
120 上滚
火狐的 滚动事件名都不一样
DOMMouseScroll 只能通过DOM 二级事件监听
event.detail 滚动的幅度
3 下滚
-3 上滚
只有谷歌和ie有onmousewheel事件属性,默认值为null
火狐根本就没有onmousewheel属性,为undefined
*/
/*
oW.addEventListener("mousewheel",function (e) {
console.log(e.wheelDelta);
})
*/
//只能通过创建一个新的节点来判断兼容
if(document.createElement("div").onmousewheel === null){
console.log("谷歌");
}else{
console.log("火狐");
}
兼容的事件监听
var oW = document.getElementById("wrap");
//元素的事件
var fn = addEvent(oW,'click',function () {
this.style.backgroundColor = 'red';
});
//文档双击移除事件
addEvent(document,"dblclick",function () {
removeEvent(oW,'click',fn);
})
//滚轮事件
addEvent(oW,'mousewheel',function () {
console.log('我滚动了');
})
//添加监听事件
function addEvent(ele,eType,callback,capture) {
//主流浏览器
if(ele.addEventListener){
//兼容一下火狐的滚轮事件
if(eType === 'mousewheel' && document.createElement("div").onmousewheel === undefined){
eType = 'DOMMouseScroll';
}
ele.addEventListener(eType,callback,capture);
return callback;
}else{
//处理ie的this指向,ie低版本不支持bind
var codeCall = function(){
callback.call(ele);
}
ele.attachEvent('on'+eType,codeCall);
return codeCall;
}
}
//移除事件
function removeEvent(ele,eType,callback,capture) {
ele.removeEventListener? ele.removeEventListener(eType,callback,capture)
: ele.detachEvent("on"+eType,callback);
}
兼容的文档滚动
//自定义滚动
addEvent(oW,'mousewheel',function (event) {
event = event || window.event;
var dir;
if(event.detail){ //火狐的滚动值
dir = event.detail / 3; //下滚
}else{
dir = event.wheelDelta / -120; //下滚
}
//console.log(dir);
this.scrollTop += dir*50;
})
21.5 案例 自定义滚动条
Title
-
1. It is never too old to learn.
活到老,学到老。
-
2. There is no royal road to learning.
学问无坦途。书山有路勤为径,学海无涯苦作舟.
-
3. A man becomes learned by asking questions.
不耻下问才能有学问。
-
4. A young idler, an old beggar.
少壮不努力,老大徒伤悲。
-
5. Study to be what you wish to seem.
学习可成为你所理想的人物。
-
6. By reading we enrich the mind, by conversation we polish it.
读书使人充实,交谈使人精明。
-
7. Books and friends should be few but good.
读书如交友,应求少而精。
-
8. Readingis to the mind while exercise to the body.
读书健脑,运动强身。
-
9. A good beginning makes a good ending.
良好的开端就是成功的一半。 善始者善终。
-
10. No matter how bad your heart has been broken, the world doesn’t stop for your grief. The sun comes right back up the next day.
不管你有多痛苦,这个世界都不会为你停止转动。太阳照样升起。
-
11. Experience is the mother of wisdom.
实践出真知。
-
12. Don't trouble trouble until trouble troubles you.
不要自寻烦恼。
-
13. Everybody dies, but not everybody lives.
人人都会死,但非人人都曾活过。
-
14. Doing is better than saying.
行胜于言。
-
15. Commitment in many, can do. It is just a lie.
承诺再多,都做不到。那也只不是是谎言。
-
16. No cross, no crown.
不经历风雨,怎能见彩虹。
22. 表单事件
22.1 表单事件
455454
22.4 案例,限制焦点