JS第一月复习

218 阅读46分钟

JS第一月复习

JavaScript:简称JS,一种运行在JavaScript解释器、特定引擎中的弱类型解释型的面向对象语言

弱类型:变量不需要预先定义类型,变量类型由值决定
解释型:不需要编译
使用语法:
1.在HTML中:<script>js代码</script>
2.<script src="需要引入的.js文件路径"></script> 注意:在此方法中的script标签内不可再书写JS代码,代码应都书写在引入的.js文件中

输出语句/调试语句:
①.console.log(需要输出的内容)也叫打桩,可以帮助在代码书写过程中帮助你检测你的代码想 执行的结果是否成功,推荐使用的原因是因为输出的内容在控制台不会影响页面
②.document.write(需要输出的内容)输出在页面上,不推荐使用原因为输出的内容会替换掉整个 原页面
③.alert(需要输出的内容)弹出一个警示框输出内容,不推荐使用原因为如果不点掉警示框会卡住 后续代码执行

js组成:
①.ECMAScript
②.Document Object Model:DOM,操作HTML
③.Browser Object Model:BOM,操作浏览器

变量:一个值是可以改变的自定义容器,类型由值决定(这是用的最多的)

语法:var 变量名 = 值;

注:这里的“=”是赋值 不是等于,在JS中等于为“==”,且变量名不能以数字开头,不能为关键字,如果以name为变量名则此变量只能装字符串类型值,不是字符串也会转为字符串类型。在一次性创建多个变量的时候,var可以不用每创建一个就写一个,多个变量定义间用逗号隔开结束用分号可省略中间的var。
一个变量只定义不赋值,默认为undefined

常量:一个一旦定义赋值后值就不能再改变的容器(用得较少)

语法:const 常量名 =值

数据类型

1.原始类型/值类型:
数字类型 number
布尔类型 boolean 取值只有两个,true/false
字符串类型 string
undefined
null 空,可以用来释放变量
2.面向对象类型:
*String Number Boolean -> 他们三个拥有包装类型
*Array *Function Date(日期) Math(数学) *RegExp(正则:验证)
Error(错误)
*Object(面向对象开发方式)
Global(全局对象) - 在浏览器中被window对象(保存着全局变量和全局函数,理论上来说确实应该对象名.操作,只不过全局对象.可以省略不写)给代替了

包装类型:专门将原始类型的值封装为一个引用类型的对象
1.当使用原始类型的变量调用方法或者属性的时候,自动包装。
2.调用的方法或者属性使用完毕后,立即释放,并返回数据
3.undefined和null不属于原始类型数据,没有包装类型所以不能使用方法与属性

STRING 字符串类型

1.多个字符组成的【只读】字符【数组】
2.字符串类型与数组一样也有下标,length属性,可以遍历字符串,所有数组的API中不修改原数组的字符串都可以使用
3.数组API中修改原数组的字符串都不能使用

STRING的API

①.转义字符:\
作用:
1、将字符串中和程序冲突的字符转为原文
2、包含特殊功能的符号 - 几乎没用
\n:字符串换行
\t:制表符 -> 大空格tab
3、*输出unicode编码的字符 - 搭配正则
\uXXXX:第一个汉字:\u4e00 ascii:19968
最后一个汉字:\u9fa5 ascii:40869
②.大小写转换:将字符串中的每个英文字母统一的转为大写 或 小写
大写:var upper=str.toUpperCase();
小写:var lower=str.toLowerCase();
③.获取字符串中指定位置的字符:var newStr=str.charAt(i)----不如直接用下标获取
④.获取字符串中指定位置的字符的ascii码
var ascii=str.charCodeAt(i)
根据ASCII码转回原文
var 原文=String.fromCharCode(ascii);
⑤.*检索字符串:检查索引:获取关键字的下标
var i=str/arr.indexOf("关键字",starti);
从starti位置开始,查找右侧【第一个关键字】的位置
starti可以省略,默认从0位置开始查找
返回值:找到了,返回的是第一个关键字的第一个字符的下标
*没找到,返回-1
强调:数组也能使用此方法
鄙视题:默认只能获取到第一个关键字的下标,如何才能获取所有关键字的下标呢?
var i=-1;
while((i=str.indexOf("no",i+1))!=-1){
console.log(i);
}
⑥.截取子字符串:3种
var subStr=str/arr.slice(starti,endi+1);//和数组的用法一样
                              .substring(starti,endi+1);//用法几乎和slice相同,但是不支持负数参数
                              
.substr(starti,n);//支持负数参数,n代表的截取的个数,不必考虑含头不含尾,某些情况用此方法可能更简单 ⑦.拼接字符串:var newStr=str.concat("新字符串")拼接不如使用+号的拼接
⑧.*替换字符串
var newStr=str.replace("关键字"/RegExp,"新内容");
⑨.切割/分割字符串:
作用:将字符串转为数组
var arr=str.split("自定义切割符");
特殊:
1、切割后,切割符就不存在
2、切割符是一个空字符串"",切散每一个字符

按值传递

如果传递的是【原始类型】的值:
1.修改一个变量,另一个变量是不会受到影响的,其实是复制了一个副本给对方

2.如果传递的是【引用类型】的对象:修改一个变量,另一个变量就会收到影响了,两者使用的是同一个地址值(浅拷贝)

数据类型的转换

转数字:

1.parseInt(想要转换的元素),原理:从组成元素的第一个数据开始转换,碰到第一个非数字数据就停止,不能识别小数点,若第一个数据就是非数字则结果为NaN

2.parseFloat(想要转换的元素),原理:从组成元素的第一个数据开始装换,碰到第一个非数字数据就停止,能识别遇到的第一个小数点,若第一个数据就是非数字则结果为NaN

3.Number(X),万能,但因为其完全等效于隐式转换不推荐使用

转字符串

1.x.toString()不能为null、undefined

转布尔值

语法:Boolean(x),一般我们不会主动去转换为布尔值。
会转换成false的六个数据:
①.0
②.""(空字符串)
③.undefined
④.NaN
⑤.null
⑥.false

算术运算符:+ - * / %

%:取余 作用是得到两数相除所得的余数

算术运算符的隐式转换:- * / % 在参与运算的字符串是纯数字组成的前提下,会自动将字符串转换为数字类型再参与 算术运算。但+号除外,当+号两边任意一边出现字符串,+号就不再是算术运算+的意思而为拼 接,会将参与的字符串跟后面的元素相拼接组成另一个字符串。
一些值转换为数字的结果:
true----1
false---0
undefined---NaN
null-----0
"150px"----NaN
NaN:not a number 虽然翻译字面意思为不是一个数字,但其本身是一个数字类型,参与任何 算术运算的结果都为NaN,参与任何比较运算结果都为false
判断一个元素是不是NaN:
isNaN(想要判断的元素),结果为true则是一个NaN,结果为false则是一个有效数字
!isNaN(想要判断的元素),结果与上面相反
扩展:解决舍入误差:num.toFixed(n)n表示保留几位小数

比较运算符:> < == !==

比较运算符一般用于判断,其结果一定为一个布尔值
隐式转换:参与比较运算的两边会默认转换为数字,再进行比较
特殊:
①.当比较两边都为字符串的时候,则为按位PK字符对应的十六进制的unicode号(十进制ascii码)
扩展:获取字符串字符的ascii码:var ascii = str.charCodeAt(n) 你表示想取字符串中第几个字符,相当于下标,从0开始,所以当n为0表示取第一个字符的ascii码
②.常识:数字<大写字母<小写字母<汉字
③.NaN参与任何比较运算结果都为false
④.如何区分null与undefined:不能用 == 需要用全等 ===,全等为true的条件为两边数据的数据类型以及值都相等

逻辑运算符:&& || !

隐式转换:默认将参与的条件都转换为布尔值,再比较
1.&& 与:当所有条件都满足时结果为true,当有任意一个条件不满足时结果都为false
2.|| 或:当有任意一个条件满足时结果为true,当所有的条件都不满组时结果为false
3.! 非:颠倒布尔值:!true----false !false---true 特殊:
①&& 短路:
若前一个条件结果为true,才会执行后一个结果
若前一个条件结果为false,则不会执行后一个结果
短路语法:条件&&(操作1);条件为true,则执行操作1.相当于简化的IF简单语句
注意:&&短路里的操作只能是一句话,不能做多个操作

②.|| 短路
若前一个条件结果为true,则不会看后面的
若前一个条件结果为false,才会看后面的
使用场景:一般用于后期针对IE做浏览器兼容
语法:e=e||window.event

位运算

左移:m<<n,表示m左移n位,等于m*2的n次方
右移:m>>n,表示m右移n位,等于m/2的n次方
缺点:底数只能为2

赋值运算

= += -= *= /= %= ++ --
赋值运算:先对数据进行运算,再返回值保存
举例:
递增:
i++一次只增加1
i+=n 每次增加n
前++,后++:
1.两个在单独存在的时候没有区别都表示变量每次递增1
2.当他们参与其他表达式的时候:
①.前++:++i表示先将变量i+1,再返回i值参与表达式。 ②.后++:i++,表示先用i值参与表达式,再对i值+1返回给i。 特殊,不管双方参不参与表达式,++的变量都会每次递增1,区别在于参与表达式的是递增之前的旧值,还是递增之后的新值

函数:一个需要先定义的可以反复使用的代码段

1.创建函数:
①.声明方式
function 函数名(形参1,形参2.....){函数体;return 返回值;} 注意:形式参数需要与否要看函数中的代码段数据是否需要另外传入(若你希望函数的执行是不变的那就不需要带有形式参数,若你希望函数随着传入的数据不同实现的操作也略微不同,那就需要形式参数)
②.直接量方式:
var 函数名=functi(形参1,形参2.....){函数体;retur 返回值;} 特殊: ①.形式参数:是一个没有var定义且暂时没有赋值的变量
②.return表示退出函数,若后面跟一个返回值,则会把返回值的数据返回到外部作用域,但只负责返回,不负责保存,通常如果需要使用这个返回值,需要一个变量来保存这个返回值。
③.就算没写return,函数一会默认返回一个undefined

2.调用函数:
①.在Js代码中直接书写 函数名(实参1,实参2.....){函数体;}注意:若函数带有形式参数,则需要传入实际参数,且实际参数填写时需要与形式参数一一对应,切此方法调用一次执行一次
②.绑定在页面元素中,由用户来触发,触发一次,执行一次
<元素名 on事件名:函数名()></元素名>

预定义全局函数:前辈们预先定义好的函数,可以直接使用

1.解码与编码:
语法:编码 var code = encodeURLComponent(str)
解码 var str -= decodeURLComponent(code)

2.isFinite(num) 判断num是不是一个无理数:true代表是一个有效数字;false表示是一个无理数。
结果会为false的值:分母为0、NaN、false

函数对象

1、创建:3种
1、*声明方式:function 函数名(形参,...){函数体;return 返回值}; - 会完整的声明提前
2、直接量方式:var 函数名=function(形参,...){函数体;return 返回值}; - 只有函数名部分会提前,但是赋值留在原地的,通过这个方法我们看出来函数名其实就是一个变量名
3、*构造函数方式:var 函数名=new Function("形参1","形参2",..."函数体;return 返回值");
何时使用:如果你的函数体不是固定的而是动态拼接的一个字符串
var arr=[12,5,25,432,7,54,4312,41];
var user=prompt("请进行排序,如果输入a-b则为升序排列,如果输入b-a则为降序排列")
var compare=new Function("a","b","return "+user);
arr.sort(compare);

2、调用时,如果还有return,记得接住:
var result=函数名(实参,...);

3、考点:
1、创建的方式
2、作用域:变量的使用规则:优先使用局部的,局部没有找全局,全局没有则报错
3、声明提前

4、按值传递
5、重载overload:相同的函数名,根据传入的实参的不同,可以自动选择对应的函数进行执行
为什么:减轻程序员的压力
问题:js的语法不支持重载
js不允许多个同名函数同时存在,如果同时存在,最后的会覆盖之前所有的
解决:在【函数中】有一个对象 - arguments对象
什么是arguments:只能在函数中使用,自动创建,是一个类数组对象(支持下标、length、遍历)
作用:可以接收住所有的传入的实参
arguments可以做的事:
1、实现重载:通过在函数内部判断arguments的不同,执行不同的操作
2、以后有没有形参都无所谓啦
3、正式开发中,有可能会将多个函数整合为一个函数 - 减轻程序员的压力
6、匿名函数:没有名字的函数
1、匿名函数自调
为什么:节约内存,因为匿名函数,没有变量引用着,用完,垃圾回收器就会发现此引用类型没有人引用着,则垃圾回收器的计数器为0,垃圾回收器就会吧此函数释放掉
(function(){
//以后可以代替全局代码写法,尽量的不要再去外部书写任何代码
})();
2、匿名函数回调:将函数作为了一个实参,传递给其他函数调用
1、*学习回调的目的:让你们知道哪些东西叫做回调函数,只要是匿名函数,没有自调,就是回调
arr.sort(function(){})
str.replace(reg,function(){})

elem.onclick=function(){}

函数的执行原理

1、程序加载时:
创建执行环境栈(ECS):保存函数调用顺序的数组
首先压入全局执行环境(全局EC)
全局EC引用着全局对象window
window中保存全局变量和全局函数
2、定义函数时
创建出函数对象:封装代码段
在函数对象中有一个scope(作用域)属性:记录着此函数来自的作用域是哪里
全局函数的scope都是window
3、调用前
在执行环境栈(ECS)压入新的EC(函数的EC)
创建活动对象(AO):保存着本次函数调用时用到的局部变量
在函数的EC中有一个scope chain(作用域链)属性引用着AO
AO有一个parent属性是函数的scope引用着的对象
4、调用时:有了前面三步,就有了变量的使用规则:优先使用局部的,局部没有找全局,全局没有就报错
5、调用完:函数的EC会出栈,AO自动释放,局部变量也就自动释放了

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

1.使用方式:
①、两个函数进行嵌套
②、外层函数创建出受保护的变量
③、外层函数要return出内层函数
④、内层函数要去操作受保护的变量
function f1(){
创建的受保护的变量
return function(){
操作受保护的变量
}
}
2.缺点:受保护的变量,永远不会被释放,使用过多,会导致内层泄漏
用于:防抖节流
需要使用防抖节流的事件:
①、elem.onmousemove - 鼠标移动事件
②、input.oninput - 每次输出/改变都会触发
③、window.onresize - 每次窗口的大小发生变化就会触发
语法:
function fdjl(){
var timer=null;//2
return function(){//3、
if(timer){clearTimeout(timer);timer=null}//关闭之前的定时器
timer=setTimeout(function(){//开启定时器,等1s才执行
//想做的操作
},延迟的毫秒数)
}
}
var result=fdjl();

考点:
两链一包:作用域链:以函数的EC的scope.chain属性为起点,经过AO逐级向上引用查找变量形成的一条链式结构

递归

何时使用:遍历DOM,专门用于【遍历层级不明确】的情况 - 不光可以遍历层级不明确的DOM树,还可以遍历层级不明确的数据
如何使用递归:2步
function 函数名(root){
1、第一层要做什么操作就直接做
2、判断他有没有下一级,如果有下一级再次调用此方法,但是传入的实参是下一级
}
函数名(实际的根节点)

算法:深度优先!优先遍历当前节点的子节点,子节点遍历完毕才会调到兄弟节点
缺点:同时开启大量的函数调用,消耗能存,只有一个情况采用:【遍历层级不明确】

分支结构

if语句

语法:
①.一个条件一件事 if(条件1){操作}
②.一个条件两件事 if(条件1){操作1} else{操作2}
③.多个条件多件事 if(条件1){操作1} elseif(条件2){操作2}......else{操作}

三目运算:简化IF...else,if...elseif...else

语法:条件1?操作1:条件2?操作2.......:默认操作
特殊:
①.默认操作不能省略
②.三目运算中的操作只能是一句话,不能做多个操作

Switch语句

语法:switch (条件){case 值1:操作1;break;case 值2:操作2;break;.........default:默认操作}
特殊:
①.case中的比较不带隐式转换
②.在执行完第一个符合条件的case之后,会继续执行后面的case,若不想执行后面的case使用break退出循环,具体是每一个case后面都带有break还是不带还是部分带要看想要实现的目的具体分析
③.default可以省略

扩展:分支结构的if语句与switch语句在面试时会遇到的问题:比较switch语句与if语句
1.switch语句 缺点:必须要知道条件的结果,不能范围比较;优点:效率相对较高
2.if语句:缺点:效率相对地下;优点:可以范围比较
建议:在优化代码的时候,尽量将if语句换成switch语句或者三目运算或者短路

循环结构

循环:希望代码反复执行相同或者相似的操作
必要元素:
1.循环条件:决定循环的开始结束以及循环次数的条件
2.循环体:再循环中执行的操作
3.循环变量,循环变量的变化:创建循环变量,一般使其朝着不满足循环条件变化

while语句

1.语法: var 循环变量名 = 值;
while(循环条件){
循环体;
循环变量变化;
}
执行原理:当循环条件结果为true就执行一次循环,再返回判断循环条件直到判断循环条件结果为false则退出循环

while语句死循环:当循环不确定次数时
while(1/true){
循环体;
}
注意:死循环往往需要配套循环流程控制语句break使用,用来强制退出循环,break可以在任何循环结构中出现不仅仅是死循环

do while语句

1.语法:
do {循环体;变量变化}while(条件)
do while语句无论第一次的条件满足还是不满足,都会执行一次循环,whlie语句不会

循环流程控制语句

1.break:退出整个循环
2.continue:退出当前循环,继续执行之后的循环

for语句

1.语法:
for(var 循环变量=值,循环条件,循环变量的变化){
循环体;
}
注意:循环变量可同时定义多个,中间用逗号隔开

for语句的死循环:
语法:for(;;){
循环体;
}
注意:同样需要配合循环流程控制语句break,来强制退出循环

作用域

1.全局作用域:全局函数,全局变量,特点:全局函数与全局变量在页面的任何地方都能够使用
2.函数作用域:局部函数,局部变量,特点:局部函数与局部变量只能在其对应所在函数内部使用
特殊:
①.函数作用域能够使用全局变量,但全局作用域不能使用局部变量,想要使用局部变量要搭配return返回想要使用的局部变量并用一个全局变量保存。
②.局部作用域优先使用局部变量,没有再使用全局变量,若都没有就报错

声明提前:在写代码的时候严格遵守规则一般不会遇到,主要在面试题中会被考

在程序执行之前,页面会将所有的声明变量(轻),声明函数(重)提前定义到当前作用域的最顶部,赋值保留
特殊:
①.声明方式创建的变量与函数会整体提前
②.直接量创建的变量与函数只会提声明部分:
事例:var a=100
function num (){
console.log(a)
var c=200;
a=5000}
var b=100
var sum =function (){函数体;}
声明提前后:
var a
var b
function num (){
var c
console.log(a)
c=200
a=5000}
var sum
b=100
sum=function (){函数体;}

数组:可以保存多个数据

1.语法:
①.var 数组名=[];中括号里面装需要装入的数据,没有数据则为一个空数组
②.var 数组名=new Array();括号里面装需要装入的数据,没有数据则为一个空数组

2.数组中的数据都有一个且唯一一个位置序号,称之为下标,用来表示数据在数组中的位置,从0开始到数组最大长度-1结束

3.访问/获取数组中的某一个元素:
数组名[对应下标]

4.修改/添加数组中的数据:
数组名[对应下标]=新元素
注意:当对应下标处有数据,上述操作则为覆盖/修改;若对应下标处没有数据,上述操作则为添加。若这里的对应下标超出了数组的最大长度,称为下标越界,会导致数组称为一个稀疏数组,在后续的遍历操作中会得到undefined。

5.数组的三大不限制:
①.不限制数据类型
②.不限制长度
③.不限制下标越界

6.数组的唯一属性:长度 length
语法:数组名.length;

length属性可以实现的三个固定套路:
①获取倒数第n个数据:数组名[数组名.length-n]
②向数组末尾添加新元素:数组名[数组名.length]=新元素
③缩容,希望删除数组倒数n个数据:数组名.length-=n

7.遍历数组:获取数组中的每一个元素用来进行操作
固定语句:for(var i=1;i<数组名.length;i++){数组名[i];}

8.hash数组:下标可以自定义的数组
语法:
var arr= []
arr["自定义下标"]=新元素

访问:arr["对应的自定义下标"]
修改:arr["对应的自定义下表"]=新元素

特殊:hash数组的length属性永久失效为0,所有遍历hash数组不能使用索引数组的方式
hash数组的遍历:for(var i in arr){arr[i];},for in循环专门为hash数组准备的,不能决定从哪里开始,也不能决定从哪里结束

hash数组的原理:
hash算法:将字符串,计算出一个尽量不重复的数字(地址值)字符串内容相同,则计算出的数字也一定是相同的
添加元素:将自定义下标交给hash算法,得到一个数字(地址值),把我的元素保存到了这个地址值之中
读取元素:将指定的自定义下标交给hash算法,得到一个和添加时完全相同的数字(地址值),根据地址值找到之前保存的东西

扩展:一切对象的底层都是一个hash数组

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

数组的API:预先定义好的一些只能给数组用的函数

1.arr.join(“自定义连接符”):将数组中数据之间的连接符定义为自定义的连接符,此方法不会修改该原数组,而是返回一个修改后的新数组
arr转字符串:arr.join(“”)

此api实现的两个固定套路:
①.无缝拼接:将数组的数据拼接为一句话或者一个词:arr.join(“”)
②.将数组拼接为一个DOM页面元素
先准备一个数组:var arr = [数据1,数据2......] 将数组连接符设置为标签的组成:str=""+arr.join("")+""
再将str赋值给页面元素:sel.innerHTML=str
注意:这里的赋值给页面元素必须使用innerHTML不能用innerText,因为innerHTML支持识别标签

2.数组拼接:将新元素拼接到数组末尾
var newarr = arr.concat(值1,值2,....):将传入的值添加到arr数组的末尾,不会修改原数组,返回一个修改后的新数组
特殊:支持传入的数据为数组,此API会将传入的数组打散为单个元素再添加到数组末尾

3.截取子数组:
根据传入的开始下标,结束下标截取数组:arr.slice(开始下标,结束下标+1)
特殊:
1.不会修改元素组,返回截取的元素组成的新数组
2.含头不含尾,所以结束下标应该为你想截取到的最后一个元素的下标+1
3.结束下标可以不写表示从开始下标一直截取到arr.length,开始下标结束下标都可以不写表示截取整个arr

4.删除、插入、替换:
语法:arr.splice(开始下标,n,值1,值2....),n为删除的个数,后面的值1值2表示删除后在开始下标出开始添加的新元素,若n为0则是向数组中从开始下标开始添加新元素,若n不为0则为从开始下标开始删除n个元素,再从开始下标开始值1值2等新元素
特殊:
1.插入新元素会将原有元素以及后续元素往后顺延
2.此API会修改原数组,返回值为你删除的元素组成的新数组,若n为0则返回空数组
3.不要插入一个数组,会导致数组变成一个部分二维数组
4.插入元素不用与删除的元素个数相对应

5.反转数组:arr.reverse():颠倒数组的元素顺序

6.数组的排序:arr.sort()
问题1:默认将数据们转为字符串,按位PK每个字符的ASCII码
解决:arr.sort(funcion(){
return a-b//升序
b-a//降序}
笔试题:手写冒泡排序:
公式:
for(var j=1;j<arr.length;j++){
for(var i=0;i<arr.length-j;i++){
if(arr[i]>arr[i+1]){
var middle=arr[i];
arr[i]=arr[i+1];
arr[i+1]=middle;
}
}
}
console.log(arr);

7.栈和队列:添加元素和删除元素的新方式:
①.栈:其实就是数组,只不过一端封闭,只能从另一端进出的数组
如何:
开头进:arr.unshift(新值,...);//添加元素的新方式:向前添加:缺点:会修改其他元素的下标,不要传入数组参数,会变成一些二维,一些一维
开头出:var first=arr.shift();//删除元素的新方式:向前删除一个,一次只会删除一个:缺点:会修改其他元素的下标
结尾进:arr.push(新值,...);//添加元素的新方式:向后添加:很棒:完美的代替了:arr[arr.length]=新值 和 arr=arr.concat(新值),不要传入数组参数
结尾进:var last=arr.pop();//删除元素的新方式:向后删除一个,一次只会删除一个

②0.队列:其实就是数组,只不过只能从一端进,另一端出的数组
开头进:arr.unshift(新值,...);
结尾进:var last=arr.pop();
结尾进:arr.push(新值,...);
开头出:var first=arr.shift();

8.判断:判断结果一定是一个布尔值 ①.every:每一个 - 要求每一个元素都要满足,结果才为true,只要有一个不满足,结果则为false - 类似&&:碰到false就不会再执行后续操作了
语法:arr.every(function(val,i,arr){
//val - 当前值
//i - 当前下标
//arr - 数组本身
return 判断条件
})

②.some:有一些 - 要求每一个元素都不满足,结果才为false,只要有一个满足,结果则为true - 类似于||:碰到true就不会再执行后续操作了
语法:arr.some(function(val,i,arr){
return 判断条件
})
9.遍历
①.forEach:遍历数组,直接修改原数组
语法:arr.forEach(function(val,i,arr){
直接做操作
})

②.map:遍历数组,不修改原数组,返回一个新数组
语法:var newArr=arr.map(function(val,i,arr){
return 操作;
})
10.汇总和过滤: ①.过滤:筛选出自己想要的,但是不会修改原数组
语法:var newArr=arr.filter(function(val,i,arr){
return 判断条件;
})

②.汇总:把数组中的每个元素都汇总到一起
语法:var result=arr.reduce(function(prev,val,i,arr){
return prev+val;
},基础值)
11.遍历API
遍历层级不明确】的情况:TreeWalker:一个在DOM树上行走的人
缺点:1、会自动跳过根节点的操作
2、只能遍历层级不明确的DOM树,而不能遍历层级不明确的数据
如何:固定公式:
1、创建tw对象:
var tw=document.createTreeWalker(根元素,NodeFilter.SHOW_ALL/SHOW_ELEMENT);
2、反复调用nextNode方法找到没一个元素
while((node=tw.nextNode())!==null){
node要做什么操作
}

DOM:用于操作html

1.DOM树:将HTML看做一个倒着的树状结构
树根:document对象,不需要我们自己创建,浏览器的JS解释器创建,一个HTML页面只有一个document
作用:提供了一些方法与属性,用来操作页面中的元素(增删改查)

面试题:
HTML/XHTML/DHTML/XML
HTML - 网页
XHTML - 更严格的网页
DHTML - Dynamic:动态的网页,其实并不是新技术、新概念,只是将现有技术的整合统称,使我们网页在离线版也具有动态效果
DHTML:HTML+CSS+JS(dom)
XML - 数据格式
2.每个DOM元素都有三大属性:
1、xx.nodeType:描述节点的类型
document节点:9
元素节点:1
属性节点:2
文本节点:3
以前有用:判断xx是不是一个页面元素 - 因为以前我们找元素的方法和大家现在不一样
2、xx.nodeValue:描述节点值,说白了就是获取属性值
以前有用:因为我们获取一个属性值没有现在这么容易
3、*xx.nodeName:描述节点名称 - 判断xx是什么标签 - 后期搭配上事件委托(利用冒泡)
注意:返回的是一个全大写的标签名
3.*API直接查找元素
1、按照HTML的特点去查找元素
1、id:var elem=document.getElementById("id值")
2、class/标签名:var elems=document.getElementsByClassName/TagName/Name("class/标签名"); 建议:表单控件元素尽量可以不写class,因为必须要写name

2、按照CSS的选择器去查找元素
1、单个元素:var elem=document.querySelector("任意css选择器");
强调:万一选择器匹配到多个元素,只会返回第一个
没找到null
2、多个元素:var elems=document.querySelectorAll("任意css选择器");
强调:找到了集合,没找到空集合
更适合做复杂查找

面试题:getXXX 和 querySelectorXXX 有什么区别?
返回结果不同:
1、getXXX:HTMLCollection - 是一个动态集合
2、queryXXX:nodeList - 是一个静态集合

动态集合:根据DOM树的改变,动态集合也会悄悄改变,每一次修改DOM树,getXXX都会悄悄再次查找元素
缺点:每次都会悄悄重新查找,效率较低,不能使用forEach

静态集合:每次修改DOM树,静态集合都不会发生变化,只会认准你找的时候的第一次找到的元素
优点:每次不会悄悄重新查找,效率较高,支持forEach

查找元素

1.通过HTML特点查找元素:
①.通过ID值查找元素:var 变量名 = document.getelementByid(“id值”),找到了返回一个单个对应元素,找不到返回null
注意:当页面中有多个重复ID值的元素,此方法返回的是第一个符合条件的元素,且返回的单个元素可直接操作,不推荐使用,ID留给后端使用

②.通过标签名查找元素:var 变量名 = document/已经查找到的父元素.getelementsByTagName(“标签名”),找到了返回一个集合,没找到返回一个空集合
注意:因为返回的是一个DOM集合,所以不能用于直接操作,可以类似于数组的操作方式,先用下标找到集合中的某一个元素,再对这个元素进行操作。
DOM集合:类似于数组,可以使用下标找到对应的某个元素,也有length属性,也可以遍历

③.通过class类名找到元素: var 变量名 =document/已经查找到的父元素.getelementsByClassName(“class类名”),找到了返回一个集合,没找到返回一个空集合
注意:因为返回的是一个DOM集合,所以不能用于直接操作,可以类似于数组的操作方式,先用下标找到集合中的某一个元素,再对这个元素进行操作。

2.通过关系查找元素
使用关系的前提是:先找到某一个元素
①.找到元素的父类元素:x.parentNode,返回一个单个元素可以直接操作
②.找到元素的子类元素:x.children,返回一个集合,不能直接操作
③.找到元素的上一个兄弟元素:x.previousElementSiBling,返回一个单个元素可以直接操作
④.找到元素的下一个兄弟元素:x.nextElementSiBling,返回单个元素,可以直接操作
⑤.找到元素的第一个子元素:x.firstElementChild,返回单个元素,可以直接操作
⑥.找到元素的最后一个子元素:x.lastElementChild,返回单个元素,可以直接操作

复合事例:x.parentNode.nextElemnetSiBling.children.lastElementChild x元素的父元素的下一个元素的子元素中的最后一个子元素

创建元素

1、创建元素:2步
1、创建空标签:var elem=document.createElement("标签名");
比如:var a=document.createElement("a");
2、添加必要的属性 和 事件
elem.属性名="属性值"
elem.on事件名=function(){操作}

以上两步只是在js内存中创建出了元素,还需要渲染到DOM树上

2、渲染页面方式:3种
*1、父元素.appendChild(新);//新元素会追加到父元素中当最后一个儿子
2、父元素.insertBefore(新,已有子元素);//新元素会追加到父元素中当儿子,会插到已有子元素的前面
3、父元素.replaceChild(新,已有子元素);//新元素会替换到父元素中当儿子,会替换已有子元素

3、删除元素:elem.remove();

操作元素

1.操作元素内容:
①.innerHTML:获取/修改元素的内容部分,这个方法可以识别内容中的标签
获取:x.innerHTML 获取X元素的内容部分,一般获取都用于判断
修改:x.innerHTML=“新内容” 修改X元素的内容

②.innerText:获取/修改元素的文本内容部分,无法识别内容中的标签
获取:x.innerText 获取X元素的内容部分
修改:x.innerText=“新内容” 修改X元素的文本内容

③.value:专门给单标签<input>准备的用来修改内容
获取:input.value 获取input标签的value值
修改:input.value=“新值” 修改input标签的value值为“新值”

2.操作元素HTML属性:注意是HTML的属性,写在HTML页面中标签内的属性
获取:x.getAttribute(“属性名”) 获取X元素的“属性名”对应的属性值
修改:x.getAttribute(“属性名”,“属性值”)修改X元素的“属性名”属性,值为“属性值”
简化用法:
x.属性名 获取X元素的“属性名”对应的属性值
x.属性名=“属性值” 修改X元素的“属性名”属性,值为“属性值”
注意:简化用法只能操作X元素自带的HTML属性,不能操作自定义属性,但.getAttribute方法可以操作自定义属性

3.操作元素的CSS样式:现阶段所学JS只能操作CSS行内样式,优点在于行内样式优先级高,可以对单个元素精准操作
获取:x.style.CSS样式名 获取X元素的CSS样式名的值
修改:x.style.css样式名=“CSS样式值” 修改X元素CSS样式名对应的样式属性值为“CSS样式值”
注意:若遇到像border-radius这种带有-的CSS样式,需要用小驼峰命名法(将横线两边的单词连着写,并且第二个单词首字母大写)

4.元素绑定事件:给元素绑定相应事件,实现让用户来触发事件
单个元素绑定:elem.on事件名=function(){操作;}
多个元素绑定:能储存多个数据的为数组,想要给每一个元素绑定事件,就需要遍历数组拿到每一个元素
for(var i=0,;i<elems.length;i++){
elems[i].on事件名=function(){操作;}
}

正则表达式:定义字符串中字符出现规则的表达式

1.语法:
①.简单的正则: 关键字原文 "no"-> /no/后缀
后缀:g:全部 i:忽略大小写

②.备选字符集:/^[备选字符集]$/
强调:
1、一个中括号,只管一位字符
2、正则表达式默认只要满足就不管后续,我们希望从头到尾完全匹配,解决:前加^后加$ - 只要是做验证就必须
特殊:如果备选字符集中的ascii是连续的,那么可以用-省略掉中间的部分
比如:
一位数字:[0-9]
一位字母:[A-Za-z]
一位字母、数字、下划线:[0-9A-Za-z_]
一位汉字:[\u4e00-\u9fa5]
除了xxx之外的:[^0-9] - 很少使用,范围太广了
③.预定义字符集:前辈们提前定义了一些字符集,方便我们程序员 - 简化备选字符集
一位数字:\d === [0-9]
一位数字、字母、下划线:\w === [0-9A-Za-z_]
一位空白字符:\s 包括:空格、换行、制表符
一位除了换行外的任意字符:. - 很少使用,范围太广了
建议:优先使用预定义字符集,如果预定义满足不了,自己在写备选字符集补充
④.量词:规定一个字符集出现的次数:
1、有明确数量
字符集{n,m}:前边相邻的字符集,至少n个,最多m个
字符集{n,}:前边相邻的字符集,至少n个,多了不限
字符集{n}:前边相邻的字符集,必须n个
2、没有明确数量
?:前边相邻的字符集,可有可无,最多1个
*:前边相邻的字符集,可有可无,多了不限
+:前边相邻的字符集,至少一个,多了不限
⑤.选择和分组:
选择:在多个规则中选一个
规则1|规则2
分组:将多个子规则临时组成了一组规则
(规则1|规则2)
⑥.指定匹配位置:
^:开头
$:结尾
特殊:两者同时使用:前加 '^' 后加"":表示从头到尾要求完全匹配<br>.密码强度验证:4位密码,数字和字母的组合,至少出现一位数字和大写字母<br>/[09AZaz]4" :表示从头到尾要求完全匹配<br> ⑦.密码强度验证:4位密码,数字和字母的组合,至少出现一位数字和大写字母<br> /^[0-9A-Za-z]{4}/
预判公式:
/^(?![0-9]+)规则)规则/ -> 不能全由数字组成
/^(?![a-z]+)规则)规则/ -> 不能全由小写字母组成
/^(?![0-9a-z]+)[09AZaz]4)[0-9A-Za-z]{4}/; - 不能全由数字组成,也不能全由小写字母组成,也不能由数字和小写的组合组成 - 至少一个大写字母
//4位密码,数字和字母的组合,至少出现一位数字和大写字母
var reg=/^(?![0-9a-z]+)(?![AZaz]+)(?![A-Za-z]+)[0-9A-Za-z]{4}/<br>//4位密码,数字和字母的组合,至少出现一位数字和大写字母和小写字母<br>varreg=/(?![09az]+/<br> //4位密码,数字和字母的组合,至少出现一位数字和大写字母和小写字母<br> var reg=/^(?![0-9a-z]+)(?![A-Za-z]+)(?![AZ09]+)(?![A-Z0-9]+)[0-9A-Za-z]{4}$/

正则表达式支持的API

1.切割:var arr=str.split(reg);

2.替换:
①.基本替换法:缺陷:替换的新东西是固定的
str=str.replace(/正则表达式/后缀,"新内容")
//replace支持正则,并且搭配上后缀就可以找到全部关键字进行替换
②.高级替换法:
str=str.replace(/正则表达式/后缀,function(a,b,c){
//第一个形参是正则匹配到的关键字
//第一个形参是正则匹配到的关键字的下标
//原文本身
return a.length==2?"":"*";
})
③.格式化:
var str="500103198602215933";
var reg=/(\d{6})(\d{4})(\d{2})(\d{2})(\d{4})/;

str=str.replace(reg,function(a,b,c,d,e,f,g,h){
//在replace的时候,正则出现了分组,我们会得到更多的形参
//有多少个分组就会多出现多少个形参
//第一个形参是正则匹配到的关键字
//第二个形参会得到第一个分组获取到的部分
//第三个形参会得到第二个分组获取到的部分
//...
return b+"年"+c+"月"+d+"日"
})
console.log(str);

正则对象

1.创建:
var reg=/正则表达式/后缀;
var arr=new RegExp(“正则表达式”,“后缀”)
2、API:验证
var bool=reg.test(用户输入的内容);
true->验证通过 false->验证失败

Math对象:提供数学计算的API

1.Math.PI:圆周率

API

1、取整:3种
1、上取整:超过一点点,就取下一个整数
Math.ceil(num);
2、下取整:无论超过多少,都会省略掉小数部分
Math.floor(num);
3、四舍五入取整:
Math.round(num);
笔试题:不允许使用.toFixed的情况下,实现to.Fixed的功能:
function round(num,d){
num*=Math.pow(10,d);
num=Math.round(num);

num/=Math.pow(10,d);
return num;
}
var result=round(3.5,0);

console.log(result);
2.乘方和开方
乘方:Math.pow(底数,幂)
开方:Math.sqrt(num) - 只能开平方
3.最大值和最小值:
var 最大的/最小的=Math.max/min(a,b,c,d,e,f,g,....);
问题:本身不支持数组参数
解决:固定用法:
var 最大的/最小的=Math.max/min.apply(Math,arr);
apply其实有两个功能:1、借用 2、悄悄的将数组打散为单个元素
4、绝对值:把负数转为整数
Math.abs(负数)
5、随机数:网页上出现了随机的功能,底层一定用到了随机数
Math.random():在0-1之间取出一个随机的小数
可能取到0,但是不可能取到1,意味着取不到最大值
公式:
parseIny(Math.random()
(max-min+1)+min);

Date对象

创建:4种
1、*创建一个当前日期时间:

var now=new Date();
2、*创建一个自定义时间:
var birth=new Date("yyyy/MM/dd hh:mm:ss");
3、创建一个自定义时间:
var birth=new Date(yyyy,MM-1,dd,hh,mm,ss);//修改月份,从0开始的,0-11
4、*复制一个日期:
为什么:日期的所有的API都是直接修改原日期对象,无法获取修改之前的日期 所以,在执行API之前都要先进行复制,然后再操作复制后的日期
如何:var end=new Date(start);

Date 的API

分量:时间的单位
年月日星期:FullYear Month Date Day
时分秒毫秒:Hours Minutes Seconds Milliseconds
每一个分量都有一对儿getXXXX/setXXXX


其中getXXX负责获取某一个分量的值

其中setXXX负责设置某一个分量的值
特殊:
1、取值范围:
FullYear:当前的年份的数字
*Month:0-11

Date:1-31
*Day:0-6,
Hours:0-23
Minutes:0-59
2、Day星期,没有set方法
3、如果希望对某个分量进行加减操作
date.setXXX(date.getXXX+/-n);
4、格式化日期为字符串:本地格式
date.toLocaleString();//本地日期格式 - 垃圾:具有兼容性问题,在老IE上显示效果不一样

Error对象

1、浏览器自带4种错误类型:可以快速找到自己的错误
语法错误:SyntaxError
引用错误:ReferenceError
类型错误:TypeError
范围错误:RangeError - 只有一个API会碰到:num.toFixed(d);//d的取值范围只能在0-100之间

2、只要发生错误,就会报错,会导致后续代码终止,我们不希望
错误处理:就算发生错误,我们也不希望报错,而是给一个错误提示,让后续代码依然可以继续执行
语法:
try{
只放入你可能出错的代码
}cathc(err){
发生错误后才会执行
console.log(err);//err就是我们的错误提示,英文
console.log("中文的错误提示")
}
try...catch:的性能非常差:几乎放在里面的代码效率都会被降到最低
*可以用一个技术代替:分支
*开发经验:记住一切的客户端输入/用户输入都是坏人 - 你不必担心,只要你做好防护就没问题(!isNaN、正则)

3、抛出自定义错误:
throw new Error("自定义错误信息") - 只要是报错就会卡主后续代码

Object对象

面向对象三大特点:封装,继承,多态。

封装

1、*直接量方式:适合创建单个对象
var obj={
"属性名":属性值,
...
"方法名":function(){},
...
}
强调:1、其实属性名和方法名的双引号可以省略不写 - 暂时建议你加上为了以后学习的json数据格式
2、访问对象的属性和方法
*obj.属性名 === obj["属性名"]
*obj.方法名(); === obj"方法名";
建议使用.访问属性和方法,更简单
*js中一切都是对象,一切对象的底层都是hash数组
3、访问到不存在的属性,返回undefined
4、可以随时随地的添加新属性和新方法
5、希望获取出对象所有的东西:遍历:for in,obj[i]才能拿到
6、*如果你希望在对象的方法里使用对象自己的属性:写为this.属性名
*难点:this的指向:
1、单个元素绑定事件 this->这个元素
2、多个元素绑定事件 this->当前触发事件的元素
3、函数中this->谁在调用此方法,this就是谁
4、定时器中this->window
5、箭头函数this->外部对象
6、构造函数中this->当前正在创建的对象
2、预定义构造函数方式:var obj=new Object();//空对象
//需要自己后续慢慢追加属性和方法
obj.属性名=属性值;
obj.方法名=function(){};
以上两个方法都有一个缺陷:一次只能创建一个对象

3、自定义构造函数方式:2步
1、创建自定义构造函数
function 类名(name,age,salary){
this.name=name;
this.age=age;
this.salary=salary;
}
2、调用构造函数创建出对象
var obj=new 类名(实参,...);

面向对象:
优点:
1、逼格高,所有的属性和方法都保存在了一个对象之中 - 更符合现实,更有意义
2、每个功能特地分开书写,越细越好 - 便于维护
3、铁索连舟 - 一个方法触发多个方法联动

继承

1、*继承:父对象的成员(属性和方法),子对象可以直接使用
为什么:代码重用!节约内存空间!提升网站性能!
何时继承:只要多个子对象公用的属性和【方法】,都要集中定义在父对象中

2、*如何找到父对象(原型对象):保存一类子对象共有属性和共有方法的父对象
1、对象名.proto;//必须先有一个对象
2、构造函数名.prototype;//构造函数名:Array/Object/String/Number/Boolean/RegExp/Date...几乎人人都有,除了Math

3、面试题:两链一包:作用域链(查找变量)、原型链(查找属性和方法)、闭包(保护一个反复使用的局部变量)
每个对象都有一个属性:.proto,可以一层一层的找到每个人的父亲,形成的一条链式结构,我们就称之为叫做原型链
可以找到所有父对象的成员(属性和方法),作用:查找找共有属性和共有方法
最顶层是Object的原型,上面放着我们很眼熟的toString方法,怪不得人人都可以使用toString JS万物皆对象

4、有了原型对象,设置共有的属性和方法

原型对象.属性名=属性值
原型对象.方法名=function(){};

*继承的笔试题: 1、判断是自有还是共有:
1、判断自有:obj.hasOwnProperty("属性名");
如果为true,说明是自有,如果为false,可能是没有或共有
2、判断共有:
if(obj.hasOwnProperty("属性名")==false&&"属性名" in obj){//in关键字会查找整条原型链
共有
}else{
没有
}

完整版:
if(obj.hasOwnProperty("属性名")){
自有
}else{
if("属性名" in obj){
共有
}else{
没有
}
}

2、修改&删除:自有和共有
自有:修改:obj.属性名=新值;
删除:delete obj.属性名;
共有:修改:原型对象.属性名=新值; - 千万不要直接在本地做操作,非常危险,添加上一个同名属性
删除:delete 原型对象.属性名; - 如果对本地删除,没有任何效果的

3、如何为老IE的数组添加indexOf方法 - 如何为一类人添加共有方法
//判断是不是老IE
if(Array.prototype.indexOf===undefined){
// //我为数组类添加了一个indexOf方法
// Array.prototype.indexOf=function(key,starti){
//原理
//用户如果没有传入开始位置,则设置为0
// starti===undefined&&(starti=0);
//从开始位置处,循环当前数组的每一个元素
// for(var i=starti;i<this.length;i++){
//每一个元素和用户传入的关键字进行比较,如果比较到了
// if(this[i]==key){
//返回下标
// return i;
// }
// }
//没找到返回-1
// return -1;
// }
// }

4、判断x是不是一个数组 - 4种方式
1、判断x是不是继承自Array.prototype;
Array.prototype.isPrototypeOf(x);//true说明是一个数组
2、判断x是不是由Array这个构造函数创建的
x instanceof Array;//true说明是一个数组

3、Array.isArray(x);//true说明是一个数组,只有数组可以这么判断,ES5提供的一个新方法,老IE都不支持

4、输出【对象的字符串】形式
在Object的原型上保存着最古老最原始的toString方法
原始的toString输出形式:[object 构造函数名]
多态:多种形态:子对象觉得父对象的成员不好用,在本地定义了同名成员覆盖了父对象的成员
固定套路:借用:Object.prototype.toString.apply(x)
if(Object.prototype.toString.apply(obj)==="[object Array]"){
console.log("数组")
}else{
console.log("不是数组")
}

5、如何实现自定义继承
1、两个对象之间继承:子对象.proto=新父对象
2、多个对象之间继承:构造函数名.prototype=新父对象
时机:应该在开始创建对象之前设置好继承关系

Object API

Object.create():希望根据父对象创建子对象,继承自动设置完毕
语法:var 子对象=Object.create(父对象,{
"自有属性":{四大特性},
...
})

ES5

1、保护对象:保护对象的成员(属性和方法)
如何保护:
1、四大特性 - 每一个属性或方法都有四大特性
如何设置四大特性:
Object.defineProperties(obj,{
"属性名":{
value: 实际保存值的地方,
writable: true/false,//开关:控制着这个属性是否可以被修改
enumerable: true/false,//开关:控制着这个属性是否可以被for in循环遍历到
configurable: true/false,//开关:控制着这个属性是否可以被删除
}
})

2、三个级别:
1、防扩展:禁止给对象添加新属性
Object.preventExtensions(obj);

2、密封:禁止给对象添加新属性和删除属性
Object.seal(obj);

3、冻结:禁止给对象添加新属性和删除属性和修改属性
Object.freeze(obj);
3.扩展的一些API
call/apply:【临时替换函数中的this】
语法:函数名.call(借用的对象,实参,...); - 单独传入每一个实参
函数名.apply(借用的对象,[实参,...]); - 只能传入一个实参,是一个数组,但是其实apply也会悄悄的将数组打散
强调:call/apply,相当于立刻调用函数,立刻执行

bind:【永久替换了函数中的this】
3件事:
1、创建了一个和原函数功能完全相同的新函数
2、将新函数中的this永久的绑定固定为了指定的对象,别人借不走
3、将新函数中的部分参数永久固定
语法:var 新函数=原函数.bind(指定对象,永久固定参数,...); - 不是立刻执行,需要自己调用
强调:bind绑定的新函数是没有办法被call/apply借走的

固定套路:
1、Math.max/min.apply(Math,arr)
2、Object.prototype.toString.call/apply(arr)==="[object Array]"
3、*类数组转为普通数组:保存一下=Array.prototype.slice.call/apply(类数组)

ES6

1、*模板字符串:可以再字符串中放入变量,不需要在做字符串的拼接了,简化了输入法的切换,还实现了一个简单的js环境<br>语法:我的名字叫{}还实现了一个简单的js环境<br> 语法:`我的名字叫{name}`

2、*块级作用域:尽量以后创建变量【优先】使用let关键字
let 变量名=值;
作用:
1、禁止了声明提前
2、添加了块级作用域:一个{}就是一个块
3、记录着当前触发事件的元素的下标

3、*箭头函数:简化回调函数
公式:去掉function,在()和{}之间添加=>,如果形参只有一个,省略(),如果函数体只有一句话,省略{},如果函数体只有一句话并且是return,return和{}都省略
特殊:千万不要将事件也简化为箭头函数 - this会失效 - 暂时

4、for of循环
for(var v of arr){
v;//当前元素
}

缺点:
1、不能修改原数组,只能返回新数组
2、不支持hash数组,不支持对象

HTML DOM常用对象

1、HTML DOM常用对象:HTML DOM就是对核心DOM进行了简化:
1、Image对象:图片对象:
简化了创建方式:var img=new Image();
不是人人都能简化创建,只有个别可以
2、Form对象:表单对象:
简化了查找元素:var form=document.forms[i];//获取页面上的第i个form元素
简化了查找表单控件元素:var inp=form.elements[i]//获取此form表单中的第i个表单空间元素
3、*Select对象:
属性:1、select.options === select.children 获取到select下面的所有option
2、*select.selectedIndex;//获取到选中项的下标
方法:1、*select.add(option);//将option上树
2、select.remove(i);//删除下标为i的option
*专属事件:onchange - 选中项发生改变后才会触发
4、*Option对象:
简化了创建方式:var opt=new Option("innerHTML","value");
建议你,如果以后希望创建出opt并且放到select中:一句话完成4个操作
select.add(new Option("innerHTML","value"))