笔记整理

114 阅读26分钟

1、✳✳✳数据类型转换

1. 强制转换:3类

1、转字符串
1、x.toString();//x不能是undefined和null - undefined和null不能.
2、ring(x);//万能的,任何人都可以转为字符串,不重要
不重要的原因:
①页面上一切的数据都是字符串
②ring(); 完全相当于隐式转换 - 还不如+""
2、✳转数字:
1、✳parseInt/Float(str);//专门为字符串转数字准备的
原理:从左向右依次读取每个字符,碰到非数字字符就停止,如果一来就不认则为NaN,
Int不认识小数点,Float认识第一个小数点
3、转布尔:
Boolean(x);//万能的,任何人都可以转为布尔,不会手动使用的,还不如:!!x
✳✳✳只有6个会为false:0,"",undefined,null,NaN,false,其余都为true
在分支、循环的条件之中,以后不管代老师写的是什么,他都会悄悄的隐式转换为布尔值,你只需要考虑为true还是为false

2、隐式转换:都是出现在运算符之中

2、✳✳✳✳运算符和表达式:

1、*算术运算符:+ - * / %

特殊:
1、%:取余,判断奇偶性
2、隐式转换:默认转为数字,在运算
true->1
false->0
undefined->NaN
null->0
特殊:
1、+运算,碰到字符串,拼接
2、-*/%:字符串可以转为数字,但是纯数字组成才行,但凡包含一个非数字字符,则为NaN

2、✳比较运算符:> < >= <= == != === !==

结果:布尔值
隐式转换:默认,转为数字,再比较大小
特殊:1、如果参与比较的左右两边都是字符串,则是按位PK每个字符的十六进制unicode号(十进制ascii码)
0-9<A-Z<a-z<汉字:常识:
汉字的第一个字:一:unicode:4E00 - ascii:19968
最后一个字:龥:unicode:9FA5 - ascii:40869

2、NaN参与任何比较运算结果都是false,所以没有办法用普通的比较运算判断是不是NaN
!isNaN(x);

3、undefined==null;//true
区分:undefined===null;
=== !==:不带隐式转换的等值比较和不等比较,要求数值相同,并且数据类型也要相同

3、✳逻辑运算:

	&&:全部满足,才true	<br>
            一个不满足,则false<br>

||:全部不满足,才false
一个不满足,则true

!:颠倒布尔值
特殊:
短路逻辑:如果前一个条件,已经能够得出最后结论了,则不看后续
&&短路:如果前一个条件满足,才执行后续操作,如果前一个条件不满足,则不管后续操作
目的:简化【简单的】分支:1、一个条件一件事满足就做,不满足就不做 if(){}
2、操作只能有一句话
条件&&(操作);
举例:原来:if(money>=500){money*=0.8};
现在:money>=500&&(money*=0.8);

||短路:浏览器兼容:二选一操作
e=e||window.event;

4、位运算:

左移:m<<n,读作m左移了n位,翻译:m*2的n次方
右移:m>>n,读作m右移了n位,翻译:m/2的n次方
缺点:底数只能2

5、赋值运算:+= -= *= /= %=

一个操作两件事,先计算,在赋值回去。
i++;//递增:每次只会固定+1
i+=1;//累加:每次+几由我们程序员自己决定
i++ === i+=1 === i=i+1;

鄙视题:++i和i++的区别:
单独使用,放前放后无所谓,效果一样。
但是如果参与了别的表达式,变量中的值都会+1
前++返回的是加了过后的新值
后++返回的是加了之前的旧值

6、三目运算:简化if...else 简化if...else if...else

语法:
1、条件?操作1:默认操作;

2、条件1?操作1:条件2?操作2:条件3?操作3:默认操作;

特殊:
1、只能简化简单的分支 - 操作只能有一句话
2、默认操作不能省略

总结:
if === &&短路
if else === 三目
if else if else === 三目

计算机带有摄入误差:解决:num.toFixed(d);//d代表保留的小数位数,会四舍五入自动进制
缺陷:搭配上一个parseFloat使用最好,结果返回的是一个字符串
获取字符串中第一个字符的ascii码:str.charCodeAt(0);

1、✳✳✳✳✳自定义Function:

什么是函数:需要先定义好,可以反复使用的一个代码段
何时使用:1、不希望打开页面立刻执行 2、以后可以反复使用
3、希望绑定在页面元素之上
如何使用:

1、创建并且调用:2种

1、创建
✳1、【声明方式】创建函数
function 函数名(形参,...){
函数体;
return 返回值/结果;
}

2、【直接量方式】创建函数 - 无用
var 函数名=function(形参,...){
函数体;
return 返回值/结果;
}

2、调用
var 接住返回的结果=函数名(实参,...);

//其实return的本意退出函数,但是如果return后跟着一个数据,
//顺便将数据返回到函数作用域的外部,但return只负责返回,不负责保存
//就算省略return,默认也会return undefined;
//具体需不要得到函数的结果,看你自己

2、✳✳✳作用域:2种

1、全局作用域:全局变量 和 全局函数,在页面的任何一个位置都可以使用

2、函数/局部作用域:局部变量 和 局部函数,在【当前函数调用时内部可用】
✳变量的使用规则:优先使用自己的,自己没有找全局,全局没有报错
特殊:缺点:1、千万不要再函数中对着未声明的变量直接赋值 - 全局污染
2、局部可以用全局的,但是全局不能用局部的 - 解决:看上面return

3、✳✳✳声明提前:

在程序正式执行之前
将var声明的变量(轻)和function声明的函数(重)
都会悄悄集中定义在当前作用域的顶部
但是赋值留在原地

声明方式创建的函数会完整的提前(第一种方式)
直接量方式创建的函数不会完整提前,只有变量部分会提前(第二种方式)

何时使用:永远不会自己使用,垃圾干扰我们判断 - 只会在鄙视中遇到,为什么平时开发根本不可能遇到它?
只要你遵守以下原则:
1、变量名和函数名尽量的不要重复
2、先创建后使用
3、如果鄙视时需要先试用后创建,多半都是在考你声明提前

4、✳✳✳按值传递:两个变量之间赋值,分两种情况
如果传递的是原始类型的值:
修改一个变量,另一个变量是不会受到影响的,其实是复制了一个【副本】给对方

如果传递的是引用类型的对象:
修改一个变量,另一个变量是会受到影响的,引用类型其实根本没有保存到变量中,仅仅只是保存了一个地址值
两者用的是同一个地址值,所以会相互影响

2、预定义全局函数:前辈们提前定义好的,我们程序员可以直接使用的,在任何位置都可以使用

✳parseInt/Float/isNaN/eval... 其实都是预定义全局函数,但是alert/prompt不属于我们现在学的范畴:确实也是全局预定义函数,只不过属于BOM

1、编码和解码

问题:url中不允许出现多字节字符(汉字,utf-8编码格式下,一个汉字占3字节),如果出现会乱码
解决:发送前,前端将多字节字符编码为单字节字符(数字、字母、符号)
发送后,后端将单字节字符在解码为多字节原文
如何:
编码:var 不认识=encodeURIComponent("大梵");
解码:var 原文=decodeURIComponent(不认识);
这个东西没有用,在某一次浏览器更新后,当前就被淘汰了,浏览器自带此功能 - 唯一的用处,现在就是玩了:悄悄话

2、isFinite(num):判断num是不是有效范围 - 垃圾并不能用于判断是不是NaN,因为有三个人会是false哪些会为false:NaN,Infinity,分母为0

3、✳✳✳分支结构:根据条件的不同,选择部分代码执行

1、if分支

2、三目&短路

3、switch...case...语法

switch(变量/表达式){
case 值1:
操作1;
case 值2:
操作2;
case 值3:
操作3;
default:
默认操作;
}
特殊:1、不具备隐式转换
2、问题:默认只要一个case满足后,就会将后面所有操作全部做一次
解决:break;
建议:每一个case的操作后都要跟上一个break
有的地方可以不加break:
1、最后一个操作default可以省略break
2、如果中间连续的多个操作,是相同的,也可以省略掉中间部分

面试题:if vs switch
1、switch:缺点:必须要知道最后的结果才能使用,不能做范围判断
优点:执行效率相对较高

2、if : 优点:可以做范围判断
缺点:执行效率相对较慢

建议:代码优化:尽量的将if替换为switch或者三目或短路

1、✳✳✳循环结构:宏观几乎是一瞬间执行的,相同 或 相似的 代码

1、✳var 循环变量=几;
while(循环条件){
操作;
变量变化;
}

2、do...while循环语法:
var 循环变量=几;
do{
操作;
变量变化;
}while(循环条件)

面试题:while和do...while的区别?
只看第一次,如果大家都满足,则没区别
如果不满足,while一次都不执行,而dowhile至少会执行一次

3、✳for(var 循环变量=几;循环条件;变量变化){
操作;
}

4、✳退出循环语句:
break - 退出整个循环
continue - 退出本次循环

5、死循环:while(true){} for(;;){}

forEach for in for of - 专门为遍历数组准备的

2、✳✳✳✳✳数组的基础:

1、什么是数组:一个集合可以保存多个数据
何时使用:多个相关的数据,都要集中的定义在一个集合中
为什么:因为一个好的数据结构,能够极大的提升我们程序员的开发效率

2、创建:2种
1、✳直接量方式:var arr=[值1,...];
2、构造函数方式:var arr=new Array(值1,...);
坑:new Array(num); - 懂不起:以为你是创建了一个长度为num的空数组

3、访问:数组名[下标];
添加/修改:数组名[下标]=新值;
特殊:访问时,下标越界 - 返回undefined
添加时,下标越界 - 变为稀疏数组,导致下标不连续,导致以后遍历一定会得到undefined

4、数组三大不限制
1、不限制类型
2、不限制长度
3、不限制下标越界 - 不推荐

5、数组唯一的一个属性:数组名.length - 获取数组的长度
三个固定套路:
1、末尾添加:arr[arr.length]=新值
2、获取倒数第n个:arr[arr.length-n];
3、缩容:arr.length-=n;

6、遍历数组:对数组中的每个元素执行 相同 或 相似的操作
for(var i=0;i<arr.length;i++){
arr[i];//当前次元素
}

7、✳如何释放一个引用类型:看清楚此引用类型有几个变量关联着,每个变量都要释放后,才能真正的释放干净
建议:我们的代码都要封装在一个函数中,函数中的一切变量都会自动释放

索引数组:下标都是由数字组成的数组
8、✳关联(hash)数组:下标是可以自定义的数组
为什么:索引数组的下标无具体的意义,不便于查找
如何使用:
1、创建:2步
1、创建一个空数组:var arr=[];
2、为数组添加自定义下标并且赋值:arr["自定义下标"]=新值

2、访问:arr["自定义下标"]

3、强调:hash数组length永久失效,永久为0!
问题:hash数组不能使用for遍历,必须使用 for in循环遍历数组,语法:
for(var i in 数组名){
console.log(i);//自动获得当前数组的所有的下标,不需要我们去设置从哪里开始到哪里结束
console.log(arr[i]);//当前次元素
}
牛逼:不光可以遍历hash数组,也可以遍历索引数组:
建议:hash用for in,索引用for

4、✳js中一切东西都是对象,万物皆对象,除了undefined和null,【一切对象的底层都是hash数组】

3、✳✳✳✳✳数组的API:数组的函数,前辈们定义好的,只有数组可以使用

1、✳✳✳✳✳arr 转为 str:
1、语法:var str=arr.join("自定义连接符");
作用:
1、鄙视时:给你一个数组,将他无缝拼接在一起:
var arr=["h","e","l","l","o"];
var str=arr.join("");
console.log(str);

2、拼接为页面元素:
//以后从数据库中取出数据
var cities=["-请选择-","北京","南京","西京","东京","重庆"];
//拼接成页面元素后,innerHTML是识别标签的
sel.innerHTML="<option>"+cities.join("</option><option>")+"</option>";

2、✳拼接数组:添加元素的新方式:
语法:var newArr=arr.concat(值1,arr1,...);
特殊:1、此方法不修改原数组,只会返回一个新数组
2、支持传入数组参数,悄悄的将我们传入的数组打散,不会变成二维数组

3、✳截取子数组:取出数组中想要的某一部分组成的一个新数组
语法:var subArr=arr.slice(starti,endi);
特殊:1、此方法不修改原数组,只会返回一个新数组
2、含头不含尾
3、第二参数可以省略不写,截取到末尾
4、第一个参数也可以省略不写,如果两个参数都没写,从头截取到尾 - 深拷贝(复制了一份副本)
5、支持负数参数,-1代表倒数第一个

1、✳✳✳✳✳Array API

1、✳✳✳✳✳排序:

1、鄙视时:不允许使用数组的API - 冒泡排序:拿着数组中的每一个元素,
让前一个和后一个做比较,如果前一个>后一个,两者应该交换位置:固定公式
var arr=
[32,14,43,453,6,58,56,531,5,57];
for(var j=1;j<arr.length;j++){
for(var i=0;i<arr.length-j;i++){
if(arr[i]>arr[i+1]){
var m=arr[i];
arr[i]=arr[i+1];
arr[i+1]=m;
}
}
}
console.log(arr);

2、数组的API:语法:arr.sort();
默认:悄悄的转为字符串,按位PK每个字符的unicode号,默认是按照字符串排序
问题1:希望按照数字升序排序
解决:
arr.sort(function(a,b){
return a-b;
});
原理:1、匿名函数回调,一般都是前辈们规定好的,我们只能学习怎么使用,自动调用,而且有多少对儿就会调用多少次
2、a:后一个数字 b:前一个数字
3、返回结果,如果是正数,说明后一个大
如果是负数,说明前一个大
如果是0,说明一样大
4、而我们的sort方法会根据你返回的正数负数0,来判断要不要交换位置

问题2:希望按照数字降序排列
arr.sort(function(a,b){
return b-a;
});

建议:开发中使用API排序,鄙视可能会碰到冒泡排序
强调:切记前端所有技术中:唯独只有数组可以排序,意味着以后如果网页中有一个排序功能,说明他的底层一定是一个数组

2、栈和队列:

栈:其实就是一个数组,只不过要求只能从一端进出,另一端是封闭的
何时:始终希望使用最新的数据时,现实中很少,代码中也很少
如何:
前进:arr.unshift(新元素,...) - 添加元素的新方式,建议不要添加数组
前出:var first=arr.shift(); - 删除元素的新方式,一次只能删除一个,而且是第一个

后进:arr.push(新元素,...) - 添加元素的新方式,建议不要添加数组
后出:var last=arr.pop(); - 删除元素的新方式,一次只能删除一个,而且是最后一个

队列:其实就是一个数组,只不过要求一端进,另一端出 何时:按照先来后到的顺序
如何:
前进:arr.unshift(新元素,...) - 添加元素的新方式,建议不要添加数组
后出:var last=arr.pop(); - 删除元素的新方式,一次只能删除一个,而且是最后一个

后进:arr.push(新元素,...) - 添加元素的新方式,建议不要添加数组
后出:var last=arr.pop(); - 删除元素的新方式,一次只能删除一个,而且是最后一个

2、二维数组:数组的元素,又引用着另一个数组

何时使用:在一个数组内,希望再次细分每个分类
如何使用
创建:
var arr=[
["杨杰",18,1200],
["周洁",19,1500],
["盛蕾",20,3500]
];

访问:arr[行下标][列下标];
特殊:列下标越界 - 返回undefined
行下标越界 - 报错:行下标越界确实会得到undefined,但是undefined没有资格再加[]

遍历二维数组:必然两层循环,外层循环控制行,内层循环控制列
for(var r=0;r<arr.length;r++){
for(var
c=0;c<arr[r].length;c++){
console.log(arr[r][c]);
}
}

3、✳✳✳✳✳String的概念:

1、什么是字符串:多个字符组成的【只读】字符【数组】:

1、只读:我们下周一要学习的所有的字符串的API,都不会修改原字符串,只会返回一个新字符串
2、数组:和数组有相同点:
1、可以使用下标得到某个字符
2、可以使用length获取字符串的长度
3、遍历字符串
4、数组不修改原数组的API,字符串
也可以使用(拼接 - 垃圾还不如直接+运算,截取)
当然和数组也有很多的不同点,数组修
改原数组的API,字符串一个都用不到,字符串也有十几个API等待我们学习

2、引用/对象类型:11个

*String Number Boolean - > 具有包装类型
*Array *Function Math(数学) Date(日
期) *RegExp(正则表达式:验证)
Error(错误)
*Object(面向对象)
Global - 全局对象:在前端/浏览器端/客户端/js中被window代替了:功能:保存着全局变量和全局函数,只有window可以省略不写

3、✳✳✳包装类型:专门用于将原始类型的值封装为一个引用类型的对象的(带来了属性和方法)

为什么:原始类型的值原本是不具备任何属性和方法的,但是前辈们发现我们程序员会经常操作到字符串
前辈们为了方便我们程序员,为三个原始类型提供了包装类型
何时使用:只要试图用原始类型的变量去用.调用属性和方法时,就会悄悄的用上包装类型变为对象
何时释放:方法调用完毕后,自动释放包装类型,并且返回数据(又会变回原始类型)

为什么undefined和null不能用. - 没有提供包装类型

1、正则表达式:规定字符出现的规则

1、最简单的正则:/原文/后缀
g:全部 i:忽略大小写

2、备选字符集:/^[0-9]$/

3、预定义字符集: 一位数字:\d
一位数字,字母,下划线:\w
一位空白字符:\s

4、量词: 有明确数量:
{n,m}:最少n次,最多m次
{n,}:最少n次,多了不限
{n}:只能n次

无明确数量:
?:可有可无,最多一次
+:至少一次,多了不限
*:可有可无,多了不限

5、选择和分组:
(规则1|规则2)

6、指定匹配位置
^:开头
$:结尾
特殊:两者同时出现,做验证:从头到尾完全按照我们程序员的规则来进行输入 - 完全匹配

7、预判:密码强度
/^(?![0-9A-Za-z]+)[09azAZ4˘e009˘fa5]4)[0-9a-zA-Z\u4e00-\u9fa5]{4}/ - 至少要有一位汉字

2、字符串的支持正则的API

1、切割:var arr=str.split(/正则/)

2、替换: 基本替换法:var newStr=str.replace(/正则/后缀,"新内容") - 替换的新内容是一样

高级替换法:
var newStr=str.replace(/正则/后缀,function(a){
return a.length==2?"":"*";
})

格式化:如果正则中搭配上了分组,那么会得到更多的形参
var newStr=str.replace(/正则/后缀,function(a,b,c...){
//第二个形参保存的是第一个分组匹配到的关键字部分
//第三个形参保存的是第2个分组匹配到的关键字部分
//...
return a.length==2?"":"*";
})

3、正则对象:

创建:var reg=/正则表达式/后缀;
var reg=new RegExp("正则表达式","后缀")

API:验证:var bool=reg.test(user);

4、真正做注册: 1、onfocus - 获取焦点事件 - 提示用户的
2、onblur - 失去焦点事件 - 拿用户的和正则比对
3、onsubmit - 提交事件,用于阻止提交return false;

1、Math:

1、不需要创建,直接使用 - 有浏览器的JS解释器自动创建

2、属性:Math.PI

3、API: 1、取整:
上:Math.ceil(num);
下:Math.floor(num);
四舍五入:Math.round(num);
*parseFloat(num.toFixed(d));

2、乘方和开方
Math.pow(底数,幂);
Math.sqrt(num);

3、最大值最小值:Math.max/min(a,b,c,d,e,f...);
数组比较:
Math.max/min.apply(Math,arr);

4、绝对值:Math.abs(-1);

5、✳✳✳随机整数公式:parseInt(Math.random()*(max-min+1)+min)

2、Date:- 以后来做一个倒计时

1、创建
当前时间:var now=new Date();
自定义时间:var xxx=new Date("yyyy/MM/dd hh:mm:ss")
var xxx=new Date(yyyy,MM-1,dd,hh,mm,ss)
复制时间:var end=new Date(start);
var xxx=new Date(毫秒数);//计算机保存的是从1970年1月1日至今的毫秒数

2、操作
1、两个日期之间可以相减,得到毫秒差可以换算出想要的任何一部分分量
2、API:FullYear Month Date Day Hours Minutes Seconds Milliseconds
每个都有个get和set操作,除了Day没有set date.setXXX(date.getXXX()+/-n)

3、格式化为字符串:date.toLocaleString(); - 建议自定义格式化方法,此方法有兼容性问题

未来一切的效果都是数据渲染
未来一切的效果都是很容易实现的,因为网上有一大把插件/组件库

1、Error:

1、浏览器自带四种错误类型:
SyntaxError - 语法错误:符号写错了
ReferenceError - 引用错误:没有创建
TypeError - 类型错误:不是你的方法,你使用了 - undefined和null
RangeError - 范围错误:num.toFixed(0-100);

2、错误处理:遇到错误,不要抛出错误,而给一个错误提示
try{
【可能】出错的代码
}catch(err){
err -> 错误信息,但是是英文的,一般我们自己写一个错误提示
}

效率低:还不如if...else提前判断,甚至我们以前学的!isNaN,正则都是为了控制用户去输入

3、自定义抛出错误:throw new Error

2、Function:

1、创建:
构造函数方式:var 函数名=new Function("形参1","形参2","函数体 return 返回值");

2、重载:相同函数名,根据传入的实参的不同,自动选择对应的函数执行,但是JS不支持多个同名函数
解决:arguments类数组对象,不需要自己创建,只能在函数内部使用
作用:可以接住所有的实参 - 变相实现重载

3、匿名函数:
自调:只能执行一次,就跟你把代码放在全局的效果是一样,但是他会自动释放
(function(){操作})()

回调:我们只学习如何使用,知道哪些叫做回调函数
xxx.API(function(){})
xxx.on事件名=function(){}

1、Function闭包:保护一个可以反复使用的局部变量的一种词法结构

全局:缺点:容易被污染
函数:缺点:一次性
语法:
function outer(){
受保护的变量;
return function(){
操作受保护的变量
}
}

var inner1=outer();

注意:1、外层函数调用几次,就创建了几个闭包,受保护的变量就有了几个副本
2、同一次外层函数调用创建的变量,是可以反复使用的
缺点:1、内层泄露
使用场景:防抖节流:
1、input.oninput
2、elem.onmousemove
3、window.onresize

2、面向对象:三大特性:封装、继承、多态

1、封装、创建:

1、直接量:
var obj={
属性名:属性值,
...,
方法名:function(){},
...
}

2、预定义的构造函数:
var obj=new Object();//空对象
obj.属性名=属性值
obj.方法名=function(){}

3、批量创建多个元素:自定义构造函数方式:
1、创建构造函数
function 类名
(name,age,salary){
this.name=name;
this.age=age;
this.salary=salary;
}

2、调用构造函数
var dy=new 类名("代老湿",18,35000000);
var dls=new 类名("代老湿",18,35000000);

4、访问&遍历
访问:obj.属性名 或者 obj.方法名();
遍历:for(var i in obj){
obj[i];
}

5、this的指向:
1、单个元素绑定事件:this->这个元素
2、多个元素绑定事件:this->当前元素
3、函数中出现了this->谁在调用就是谁
4、定时器this->window
5、箭头函数this->外部对象
6、构造函数中的this->当前正在创建的对象

1、✳✳✳✳✳继承:子对象可以直接使用父对象的属性和【方法】

为什么:代码重用
如何使用:1、找原型对象:2种
1、对象名.__proto__
2、构造函数名.prototype

2、设置共有属性和共有方法
原型对象.属性名=属性值;
原型对象.方法名=function(){}

3、原型链:每一个对象都有一个属性.__proto__,找到自己的爸爸甚至祖先,形成的一条链式结构就称之为叫做原型链,
哪怕自己没有此方法也可以通过原型链看看祖先上面有没有,作用:查找属性和方法
最顶层就是Object.prototype

4、笔试题:
1、判断自有还是共有
if(obj.hasOwnProperty("属性名")){
//自有
}else{
if("属性名" in obj){
//共有
}else{
//没有
}
}

2、修改和删除自有共有
自有:修改:obj.属性名=新属性值
删除:delete obj.属性名;

共有:修改:obj.__proto__.属性名=新属性值
删除:delete
obj.__proto__.属性名;

3、为一类人添加方法:
构造函数
名.prototype.API=function(){
操作
}

4、判断x是不是数组:
1、判断是否继承自Array.prototype
Array.prototype.isPrototypeOf(x);

2、判断是否由Array构造函数创建
x instanceof Array

3、是不是数组:Array.isArray(x); - 只有数组可用

4、多态:同一个函数名,但是表现出来的形式形态完全不一样,其实根本就不是同一个方法,属于的对象其实不一样
同样的toString,但是arr和obj的表现形式不要一样
Object.prototype.toString.apply(x)==="[object Array]"

5、自定义继承:
obj.__proto__=新父对象;
构造函数名.prototype=新父对象; - 注意时机:先设置继承,在创建对象

1、ES5新的API操作

1、保护对象:
1、修改四大特性
Object.defineProperties(对象名,{
"属性名":{
value:实际的值,
writable:true/false,控制着是否可以被修改 enumerable:true/false,控制着是否可以被for in遍历 configurable:true/false,控制着是否可以被删除,总开关,一旦改为false其他三大特性不可以再修改,不可逆
}
})

2、三个级别
Object.preventExtensions(对象名); - 防扩展
Object.seal(对象名) - 密封
Object.freeze(对象名) - 冻结

2、数组的API:
判断:var bool=arr.every/some((val,i,arr)=>判断条件);

遍历:arr.forEach((val,i,arr)=>操作);
var newArr=arr.map((val,i,arr)=>操作);

过滤:var subArr=arr.filter((val,i,arr)=>判断条件);
var sum=arr.reduce((prev,val,i,arr)=>操作,基础值);

3、var 子对象=Object.create(父对象,{
"自有属性名":{四大特性},
...
})

4、严格模式:"use strict";
1、静默失败升级为报错
2、禁止了全局污染

5、✳✳✳✳✳call/apply/bind:
call/apply:临时替换了函数中的this
语法:函数.call(借用的对象,实参,...)
函数.apply(借用的对象,[实参,...])
强调:立刻调用立刻执行

bind:永久替换了函数中的this
语法:var 新函数=函数.bind(绑定的对象,永久实参,...)
强调:不会立刻执行,需要手动调用

2、ES6语法的简化

1、我的名字叫${name}

2、let 变量名=值
1、解决了声明提前
2、添加了块级作用域 - {}
3、记录了当前触发事件的元素的下标

3、箭头函数
function去掉
()和{}之间添加=>
形参只有一个,省略()
函数体一句话,省略{}
函数体一句话且是return,省略{}和return

4、for(var v of arr){
v;当前值
}

不能遍历hash数组
不能操作原数组

查找元素:

0、DOM分类:
1、核心DOM
2、HTML DOM
3、XML DOM

1、直接找元素
id:var
elem=document.getElementById("id值");
className/tagName/Name:var elems=document/父元素.getElementsByclassName/tagName/Name("xxx");

选择器:
var elem=document.querySelector("任意css选择器");
var elems=document.querySelectorAll("任意css选择器");

返回:HTMLCollection - 动态集合:根据DOM树的变化,会悄悄的再次找元素 - 但是不能用forEach
NodeList - 静态集合:可以使用forEach,可以简化为箭头函数

2、关系:
父:xx.parentNode
子:xx.children
第一个儿子:xx.firstElementChild
最后一个儿子:xx.firstElementChild
前一个兄弟:xx.previousElementSibling
后一个兄弟:xx.nextElementSibling

3、层级不明确的情况:
1、递归:不能多用,只在层级不明确的情况
function dg(根形参){
1、第一层要做什么直接做

2、判断有没有下一层,有的话,再次调用此方法,传入新的实参(下一层)
}
dg(根数据/根元素)

2、遍历API:只能遍历DOM树
var tw=document.createTreeWalker(根元素,NodeFilter.SHOW_ELEMENT);
while((node=tw.nextNode())!=null){
node要干什么
}

操作元素

1、元素的内容

1、*elem.innerHTML:获取或者设置开始标签到结束标签之间的HTML代码,没有兼容性问题,可以识别标签
获取:elem.innerHTML
设置:elem.innerHTML="新内容"

2、elem.textContent:获取或者设置开始标签到结束标签之间的纯文本,但是有兼容性问题,不可以识别标签
获取:elem.textContent
设置:elem.textContent="新文本"
特殊:老IE才叫elem.innerText;//第一见到小三上位,反而所有的主流浏览器来将就了老IE

3、*input.value:获取或设置单标签(input)的内容准备的
获取:input.value
设置:input.value="新值"

2、元素的属性:

1、*获取属性值:
核心DOM:elem.getAttribute("属性名")

HTML DOM:elem.属性名;

2、*设置属性值:
核心DOM:elem.setAttribute("属性名","属性值");

HTML DOM:elem.属性名="新值";

3、删除属性值:
*核心DOM:elem.removeAttribute("属性名")

HTML DOM:elem.属性名="" - 虽然简单,但是有的情况会删不干净,有的属性删不干净依然会有功能比如:href

4、判断有没有 - 垃圾
核心DOM:elem.hasAttribute("属性名");

HTML DOM:elem.属性名!="";

返回的结果是一个布尔值,只能判断有没有,不能判断是什么

HTML DOM:有两个小缺陷:
1、class需要写为className
2、一切自定属性不能操作
3、删除删不干净,依然会留下属性节点

3、元素的样式:

1、内联样式:
获取:elem.style.css属性名
设置:elem.style.css属性名="css属性值"
特殊:
1、css属性名如果有横线要省略,变为小驼峰命名法
2、获取的时候只能获取到内联样式,这个小缺陷可以忽略不计

2、样式表: - 不推荐
//获取到你想要操作的某个样式表
var sheet=document.styleSheets[i];
//获取样式表中所有的样式规则
var rules=sheet.cssRules;
//选出自己想要操作的某个规则
var rule=rules[i];
//操作
获取:
console.log(rule.style.css属性名);
设置:rule.style.css属性名="css属性值"

为什么更推荐内联:
1、不会牵一发动全身
2、优先级一定是最高的

元素:

1、增:
var elem=document.createElement("标签名");//有两个人可以简化:new Image/Option()
elem.属性名="值"
父元素.appendChild(elem);
父元素.insertBefore(elem,已有子元素);
父元素.replaceChild(elem,已有子元素);

2、改:父元素.replaceChild(elem,已有子元素);

3、删:elem.remove();

4、查:
直接找:
var elem=document.getElementById("id值");
var elems=document.getElementsByTagName/ClassName/Name("TagName/ClassName/Name");

var elem=document.querySelector("任意css选择器");
var elem=document.querySelectorAll("任意css选择器");

关系:
父:xx.parentNode
子:xx.children
第一个儿子:xx.firstElementChild
最后一个儿子:xx.lastElementChild
前一个兄弟:xx.previousElementSibling;
后一个兄弟:xx.nextElementSibling;

层级不明确:递归
function xx(根元素/根数据){
只管第一层,判断有没有下一层,有
的话再次调用此函数,传入下一层
}

文本:innerHTML/innerText/value

1、增:xx.api+="新值";

2、删:xx.api=""

3、改:xx.api="新值"

4、差:xx.api

属性:

1、新增:xx.setAttribute("属性名","旧属性值 新属性值"); xx.setAttribute("class","d1 d2")

2、删除:xx.removeAttribute("属性名");

3、修改:xx.setAttribute("属性名","新属性值");

4、查找:xx.getAttribute("属性名");

样式:

1、新增:xx.style.css属性名="css属性值"; - 可能是改

2、删除:xx.style.css属性名=""

3、查找:xx.style.css属性名; - 只能操作内联样式

HTML DOM常用简化对象:

1、select:
属性:selected - 获取到当前选中项的下标
方法:add(option) - appendChild
事件:onchange

2、option:
var opt=new Option("innerHTML","value");

用户确认框:var bool=confirm("提示文字");