1.for in
对象中有多少组键值对,我们的FOR IN 循环就遍历多少次(不一定)
每一次循环KEY这个变量存储的都是当前循环这组键对值的属性名
1、KEY存储的值都是字符串格式的(不管属性名是否为数字)
2、在FOR IN 循环遍历的时候,大部分浏览器都是先把对象中的键值对进行排序(把数字属性名的排在前面,并且排列的时候按照数字由小到大排列),其次再把非数字的属性名按照之前编写的顺序排列,循环的时候按照重新排列的顺序依次遍历(小数算作字母不算作数字)for (var key in obj) {
console.log(typeof key) "string"
console.log(obj.key)
console.log(obj[key]);每一次循环把key变量存储的值(当前遍历的属性名)获取到放在中括号中,获取OBJ对应属性的属性值
'key':字符串key
key:变量key,代表的是存储的值
}obj['key'] obj.key 属性名是key
obj[key] 属性名不是key 而是key变量存储的值
复制代码
2. 数据类型转换
2.1 把其他数据类型转换为number类型
A) isNaN 、Number、parseInt、parseFloat
true --> 1 false --> 0 '' --> 0 '12'-->12 '12px' --> NaN/12 '帅哥' --> NaN
null --> 0 undefined --> NaN
{} /$/ function() {} --> NaN
[]
通过toString方法把数组转化为字符串,然后再调用Number把字符串转换为数字
[] --> '' -->0 [12] --> '12' -->12 [12,23] --> '12,23' --> NaNB)在进行加减乘除数学运算的时候
1、加减乘除
2、除了加法有特殊性,其余的运算符都是数学运算,也就是遇到非数字类型,需要把其转换为number再进行运算
1- '1' = 0 10 * null = 0 10/undefined = NaN . 10 * [10] = 100
加法的特殊性:
在遇到字符串的时候 + 不是数学运算 而是字符串拼接 只要不遇到字符串就是数学运算
1+ '1' = '11' null + '1' = 'null1'
字符串拼接:把其他值转为字符串然后再拼接 (toString)
其他数据类型的toString是直接把值用单(双)引号包起来即可,只有对象的有特殊性,对象.toString =' [object object]'
(1).toString --> '1' (true).toString ---> "true" null undefined 都有toString() 方法 但是浏览器不让用
[12,23].toString() "12,23" /^$/.toString() "/^$/" (function() {}).toString() "function() {}"
({name:"hou"}).toString() "[object object]"1+ null + undefined + [] +'hou' + null + undefined + [] + 101 +null ---> 1 1 + true --->2 2 + undefined ---> NaN
NaN + [] --->NaN + '' --->"NaN"
"NaN" + 'hou' + 'null' + 'undefined' + '' + '10'---> "NaNhounullundefined10"复制代码
2.2 将其他数据类型转换为布尔类型
Boolean ! !!
条件判断,也是转换为布尔类型,然后判断真假
只有 0 NaN null undefined 空字符串 五个转换为false 其余都是true
[] ---> true -1 ---> trueif (box) {首先把box 变量存储的值获取到,转化为布尔类型,如果转化为true条件成立 反之不成立
}if(3 +'3px') {
}if(3- '3px') {
}
复制代码
2.3 使用"=="进行比较
在使用"=="进行比较的时候,如果左右两边数据类型不相同,浏览器会默认转换为相同的类型,然后再比较("==="不会这样操作)
对象和对象:比较的是空间地址,不是相同的空间,结果肯定是false
[] == [] false var a = {} var b = a ; a==b true
对象和数字:把对象转换为数字
[] == 0 true
({}) == NaN false NaN和自己不相等和其他任何值都不相等
对象和字符串:把两边都转换为数字比较的
[] == '' true
对象和布尔:把两边都转换为数字
[] == true 0==1 false
[] == false 0 ==0 true
![] == false --> 把数组变为布尔再取反 = false --> false == false --> true字符串和数字:字符串转换为数字
字符串和布尔:都转化为数字
布尔和数字: 布尔转换为数字规律:两个等于号比较,左右两边数据值的类型不一样,浏览器会把两边的类型都转换为数字然后再比较,但是null 和undefined除外
null == undefined --> true
null === undefined ---> false
null以及undefined 和其他任何值都不相等
复制代码
3.Math中的常用方法:
数学函数:但是它是对象数据类型的 typeof Math 'object'
Math对象中给我们提供了很多常用操作数字的方法
abs 取绝对值
ceil 向上取整
floor 向下取整
round 四舍五入 Math.round(12.3) -->12 Math(12.5) ---> 13 正数中5包含在向上
Math.round(-12.3) ---> -12 Math.round(-12.5) ---> -12 负数5 包含在向下 Math.round(-12.51) -13
random 获取[0,1)之间的随机小数 很难获取到0
获取[0,10]之间的随机整数 Math.round(Math.random()*10)
获取[3,15]之间的随机整数 Math.round(Math.random()*12 + 3)
获取[n,m]之间的随机整数 Math.round(Math.random()*(m-n) + n)
max/min 获取一组值中的最大值和最小值
PI 获取圆周率
pow 获取一个值的多少次幂 Math.pow(10,2) --> 100
sqrt 开平方 Math.sqrt(100) ---> 10
复制代码
4.字符串常用方法:
Jstr.charAt(索引):返回指定索引位置的字符,和str[索引]的区别在于,当指定的索引不存在的时候,中括号的方式获取的是undefined,而charAt获取的是空字符串
str.charCodeAt(索引):在charAt基础上,把获取的字符变为unicode编码值(对应ASCII码表)
48-57: 0-9
65-90: A-Z
97-122: a-z
str.fromCharCode(十进制的unicode值):把值按照ASCII码表中的信息,转换为原有的字符,和charCodeAt正好对应
substr && substring && slice
实现字符串截取的三个办法
str.substr(n,m):从索引n开始 截取m个字符
str.substring(n,m):从索引n开始,截取到索引为m处(不包含m 即 m-1)把找到的部分截取
str.slice(n,m):和substring语法一样,区别在于slice支持以负数做索引
当索引是负数的时候,浏览器在处理的时候,是用字符串的总长度加上负数索引,然后按照正数处理操作
str.slice(-7,-3) ===> str.slice(str.length-7,str.length-3)
细节:
1、如果只传递了n(str.substr(n)/str.substring(n)),相当于从索引n开始一直截取到字符串的末尾
2、如果传递的索引超出最大限制,也是把能截取的部分截取掉即可
3、如果一个参数都不传递,相当于把整个字符串都截取(字符串的克隆)
str.toUpperCase:把字母全局大写
str.toLowerCase:把字母全局小写
indexOf && lastIndexOf
str.indexOf:获取当前字符在字符串中第一次出现位置的索引
str.lastIndexOf:获取的是当前字符最后一次出现位置的索引
如果当前字符在字符串中没有出现过,结果是-1 :我们根据这个规律可以验证一下当前字符串是否包含某个字符
if(str.indexOf('?') === -1) {
}if(str.indexOf('?') >=0) {
}
str.split:按照某一个字符把字符串拆分成数组中的某一项,和数组的join方法是对应的
var str = 'name=shuaige&age=8'
str.split('=')
["name","shuaige&age","8"]
str.split(/=|&/g);
["name","shuaige","age","8"]
str.split('')
["n", "a", "m", "e", "=", "s", "h", "u", "a", "i", "g", "e", "&", "a", "g", "e", "=", "8"]
str.split(' ') 不太一样 后边这个有空格 ["name=shuaige&age=8"]
var ary = [12,34,32]
ary.join('+') "12+34+32"
"12+34+32".split('+') ==> ["12","34","32"] ary 的元素是数字 变成了字符串
str.replace:实现字符的替换
执行一次replace 只能替换一次 如果我们有好几个需要替换,在不使用正则的情况下我们需要执行很多次replace
有些需求即使执行很多次replace也实现不了,此时需要使用正则处理,真实项目中replace一般都是和正则搭配使用的
trim && trimLeft && trimRight
str.trimLeft:去除字符串开始的空格
str.trimRight:去除字符串结尾的空格
str.trim:去除字符串首尾的空格字符串应用之queryURLParameter
var url = "https://www.baidu.com/s?wd=node&rsv_spt=1&issp=1"
目标:把问号传递的参数值分别的解析出来
var obj ={wd:'javascript',rsv_spt:1,issp:1}
方案一:
function queryURLParameter(url) {var quesIndex = url.indexOf('?')var obj = {};if(quesIndex === -1) {return obj;}url = url.substr(quesIndex+1);var ary = url.split('&');for(var i = 0; i < ary.length; i++) {var curAry = ary[i].split('='); obj[curAry[0]] = curAry[1];}return obj;
}方案二:待分析
String.prototype.myQueryURLParameter = function myQueryURLParameter() {var obj = {},reg = /([^=?&]+)=([^=?&]+)/g;this.replace(reg,function() {var arg = arguments;obj[arg[1]] = arg[2];});return obj;
}真实项目中的验证码:
真实项目中的验证码一般都是后台处理的,后台返回给客户端展示的是一个图片(图片中包含了验证码)
1、字母+ 数字
2、问答
3、12306 选择图片
4、成语填空
5、图片拼图
6、滑动拖拽letter-spacing:5px 文本字体之间的间距
cursor:pointer;
函数操作
var codeBox = document.getElementById('codeBox');
==>生成4位随机验证码
var areaStr = "0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
var result = '';
for(var i = 0; i < 4; i++) {var ran = Math.round(Math.random()*61);var char = areaStr.charAt(ran);if(result.toLowerCase().indexOf(char.toLowerCase())>-1) {i--; continue;}result+=char;
}
codeBox.innerHTML = result;点击盒子生成4个随机验证码
function queryCode() {.....codeBox.onclick = queryCode;禁止用户选中文字 ==》-webkit-user-select: none
复制代码
5.节点操作
DOM: document object model 文档对象模型,提供一些属性和方法可以让我们去操作DOM元素
获取DOM元素的方法
document.getElementById 一个元素对象
[context].getElementsByTagName 元素集合
[context].getElementsByClassName 通过元素类名获取元素集合
document.getElementsByName 通过name属性值获取节点集合
document ===>说明上下文不能发生变化
[context] ===> 说明上下文可以发生变化
document.documentElement 获取整个HTML对象
document.body 获取整个BODY对象
document.head 获取整个HEAD对象
[context].querySelector 通过选择器获取一个元素对象
[context].querySelectorAll 通过选择器获取元素集合getElementById ==> 此方法的上下文只能是document
一个HTML页面中元素的ID理论上是不能重复的
1、如果页面中的ID重复了,我们获取的结果是第一个ID对应的元素对象
2、在IE7及更低版本浏览器中,会把表单元素的name值当作id来识别使用(项目中尽量不要让表单的name和其他元素的id相同)
3、如果我们把JS放在结构的下面,我们可以直接使用ID值来获取这个元素(不需要通过getElementsById获取),而且这种方式会把页面中所有ID是他的元素都获取到(元素对象/元素集合) ===> 不推荐
获取页面中ID值为#box1的所有元素标签
var allList = document.getElementsByTagName('*');
var result = [];
for(var i = 0 ; i < allList.length; i ++) {
var item = allList[i];
item.id === 'box1' ? result.push(item):null;
}getElementsByTagName
上下文可以自己来指定
获取到的结果是一个元素集合(类数组集合)
1、获取的结果是集合,哪怕集合中只有一项,我们想要操作这一项(元素对象),需要先从集合中获取出来,然后再操作
var bodyBox = document.getElementsByTagName('body');
bodyBox[0].getElementsByTagName('div');
2、在指定的上下文中,获取所有子子孙孙元素中标签名叫做这个的(后代筛选)getElementsByClassName
上下文也可以随意指定
获取的结果也是一个元素集合(类数组集合)
1、真实项目中我们经常会通过样式类名来获取元素,getElementsByClassName这个方法在IE6-8浏览器中是不兼容的
getElementsByName
通过元素的Name属性值获取一组元素(类数组:节点集合NodeLIst)
它的上下文也只能是document
IE浏览器只能识别表单元素的name属性值,所以我们这个方法一般都是用来操作表单元素的document.documentElement/document.body
获取HTML或者BODY(一个元素对象)
document.documentElement.clientWidth || document.body.clientWidth//获取当前浏览器窗口可视区域的宽度(当前页面一屏幕的宽度)
clientHeight是获取高度querySelector /querySelectorAll ---->性能没有这么好
在IE6-8下不兼容,而且也没有什么特别好的办法处理它的兼容,所以这两个方法一般多用于移动端开发使用
querySelector:获取一个元素对象
querySelectorAll :获取的是一个元素集合
只要是css支持的选择器,这里大部分都支持document.querySelectorAll('#div1');//根据ID获取所有的元素
document.querySelectorAll('.box');//根绝className获取元素集合
document.querySelectorAll('div');//根据标签获取元素集合
document.querySelectorAll('body>div');//子代选择器 body下的 div
document.querySelectorAll('#box2 li');//后代选择器
document.querySelectorAll('div [name=xxxxx]');DOM的节点
node:节点,浏览器认为一个HTML页面中的所有内容都是节点(包括标签、注释、文字文本等)
元素节点:HTML标签
文本节点:文字内容(高版本浏览器会把空格和换行也当作文本节点)
注释节点:注释内容
document文档节点元素节点
nodeType:1
nodeName: 大写标签名(在部分浏览器的怪异模式下,我们写的标签名是小写,它获取的就是小写)
nodeValue: null
[curEle].tagName:获取当前元素的标签名(获取的标签名一般都是大写)文本节点 --- 空格 换行 属于文本 节点
nodeType:3
nodeName: #text
nodeValue:文本内容注释节点
nodeType:8
nodeName: #comment
nodeValue:注释内容文档节点
nodeType:9
nodeName: #document
nodeValue:nulldocument.body.childNodes节点:用来描述页面中每一部分之间关系的,只要我可以获取页面中的一个节点,那么我就可以通过相关的属性和方法获取页面中的所有节点
childNodes:获取当前元素所有子节点(节点集合:类数组)
注:不仅仅是元素子节点,文本、注释等都会包含在内;
子节点说明只是在儿子辈分中查找children:获取所有的元素子节点(元素集合) 在IE6-8下获取的结果和标准浏览器中有区别(IE6-8中会把注释节点当作元素节点获取到)
parentNode:获取当前元素的父节点(元素对象)
previousSibling nextSibling
previousSibling:获取当前节点的上一个哥哥节点(不一定是元素节点也可能文本或者注释)
nextSibling:获取当前节点的下一个弟弟节点previousElementSibling nextElementSibling
previousElementSibling:获取当前节点的上一个哥哥元素节点(IE6-8不兼容)
nextElementSibling:获取当前节点的下一个弟弟元素节点(IE6-8不兼容)firstChild lastChild
firstChild:当前元素所有子节点中的第一个(也不一定是元素节点,可能是文本和注释)
lastChild:当前元素所有子节点中的最后一个firstElementChild lastElementChild(IE6-8不兼容)DOM的增删改
真实项目中,我们偶尔会在JS中动态创建一些HTML标签,然后把其增加到页面中
document.createElement
在JS中动态创建一个HTML标签
容器.appentChild(新元素)
把当前创建的新元素增加到容器的末尾位置
insertBefore
容器.insertBefore(新元素,老元素)
在当前容器中,把新创建的元素增加到老元素之前//真实项目中很多需求是通过动态创建元素来完成的,其中有一个需求:解析一个URL地址每一部分的信息(包含问号传递的参数)
1、纯字符串拆分截取
2、编写强大的正则,捕获到需要的结果
3、通过动态创建一个A标签,利用A标签的一些内置属性来分别获取每一部分的内容
var link = document.createElement('a');
link.herf = 'http://www.zhufengpeixun.cn/stu/?name=zxt&age=27#teacher';
//此处地址就是我们需要解析的URL
hash:存储的是哈希值 '#teacher'
hostname:存储的是域名 'www.zhufengpeixun.cn'
pathname:存储的是请求资源的路径名称'/stu/'
protocol:协议'http:'
search:存储的是问号传递的参数值,没有传递是空字符串'' ===>'?name=zxt&age=27'function queryURLParameter(url) {
var link = document.createElement('a');
link.href = url;var search = link.search,
obj = {};
if(search.lenght === 0) return;
search = search.substr(1).split(/&|=/g);
//拆分完之后 奇数项是key 偶数项是value ["name","zxt","age","27"]
for(var i = 0; i < search.length; i +=2) {
var key = search[i];
value = search[i+1];
obj[key] = value;
}
link = null;
return obj;
}removeChild
容器.removeChild(元素)
在当前容器中把某一个元素移除掉
replaceChild
容器.replaceChild(新元素,老元素)
在当前容器中,拿新元素替换老元素
cloneNode
元素.cloneNode(false/true)
把原有的元素克隆一份一模一样的
false:只克隆当前元素本身
true:深度克隆,把当前元素本身以及元素的所有后代都进行克隆
[set/get/remove] Attribute
给当前元素设置/获取/移除 属性的(一般操作的都是它的自定义属性)box.setAttribute('myIndex',0);
box.getAttribute('myIndex');
box.removeAttribute('myIndex');使用xxx.index 和xxx.setAttribute('index',0)这两种设置自定义属性的区别
xxx.index:是把当前操作的元素当作一个普通对象,为其设置一个属性名(和页面中的HTML标签没关系)
xxx.setAttribute:把元素当作特殊的对象来处理,设置的自定义属性是和页面结构中的DOM元素映射在一起的JS中获取的元素对象,我们可以把它理解为两种角色:
与页面HTML结构无关的普通对象
与页面HTML结构存在映射关系的元素对象元素对象中的内置属性,大部门都和页面的标签存在映射关系:
xxx.style.backgroundColor = 'xxx' 此时不仅把JS中对象对应的属性值改变了,而且也会映射到页面的HTML标签上(标签中有一个style行内样式、元素的样式改变了)xxx.className='xxx' 此时不仅是把JS对象中的属性值改了,而且页面中的标签增加了class样式类(可以看见的)元素对象的自定义属性:xxx.index = 0
仅仅是把JS对象中增加了一个属性名(自定义的),和页面中的HTML没啥关系(在结构上看不见)
xxx.setAttribute:通过这种方式设置的自定义属性和之前提到的内置属性差不多,都是和HTML结构存在映射关系的(设置的自定义属性可以呈现在结构上)获取当前元素的上一个哥哥元素节点
首先获取当前元素的上一个哥哥节点,判断当前获取的节点是否为元素节点(nodeType ===1),如果不是,基于当前获取的节点,找他的上一个哥哥节点。。。(找几次不知道)一直到找到的节点是元素节点为止,
如果在查找过程中,发现没有上一个哥哥节点了(找到头了),则不再继续查找
function pre(curEle) {
var p = curEle.previousSibling;
//p 为null 结束 p的nodeType ===1 结束
while(p && p.nodeType !==1) {
p = p.previousSibling;//p: p!=null
}
return p;
}
//扩展
next:获取下一个弟弟元素节点
function next(curEle) {
var p = curEle.nextSibling;
//p 为null 结束 p的nodeType ===1 结束
while(p && p.nodeType !==1) {
p = p.nextSibling;//p: p!=null
}
return p;
}prevAll:获取所有的哥哥元素节点
function prevAll(curEle) {
var arr = [];
var p = curEle.previousSibling;
//p 为null 结束
while(p) {
// 如果是元素节点 放到数组中
if(p.nodeType ===1) {
arr.push(p);
}
p = p.previousSibling;//p: p!=null
}
return arr;
}nextAll:获取所有的弟弟元素节点
function nextAll(curEle) {
var arr = [];
var p = curEle.nextSibling;
//p 为null 结束 说明找到了尽头
while(p ) {
if(p.nodeType ===1) {
arr.push(p);
}
p = p.nextSibling;//p: p!=null
}
return arr;
}
siblings:获取所有的兄弟元素节点
//既要往前找 又要往后找
function siblings(curEle) {
var arr = [];
var p = curEle.previousSibling;
var n = curEle.nextSinling;
while(p) {
// 如果是元素节点 放到数组中
if(p.nodeType ===1) {
arr.push(p);
}
p = p.previousSibling;//p: p!=null
}while(n ) {
if(n.nodeType ===1) {
arr.push(n);
}
n = n.nextSibling;//p: p!=null
}
return arr;}
index:获取当前元素在兄弟中的排名索引function index() {
var arr = [];
var index = 0;
var p = curEle.previousSibling;
//p 为null 结束
while(p) {
// 如果是元素节点 放到数组中
arr.push(p);
p = p.previousSibling;//p: p!=null
}
index = arr.length;
return index;}
复制代码
6.日期操作
Date:日期类,通过它可以对时间进行处理
var time = new Date()
获取的结果是一个日期格式的对象
typeof new Date() --->'object'
time.getFullYear() 获取四位整年数
time.getMonth() 获取月(0-11 代表1-12月)
time.getDate() 获取日
time.getDay() 获取星期(0-6 代表周日到周六)
time.getHours() 获取小时
time.getMinutes() 获取分钟
time.getSeconds() 获取秒
time.getMilliseconds() 获取毫秒
time.getTime() 获取当前日期距离"1970-01-01 00:00:00"的毫秒差var time = new Date('2017-10-22');
当new Date中传递了一个时间格式的字符串,相当于把这个字符串转换为标准的时间对象格式(转换完成后 就可以调取上面我们讲的那些方法了)
时间格式的字符串
"2017-10-22"(IE下识别不了)
"2017/10/22"
"2017/10/22 16:15:34"
1508659621314 ===>传递的距离1970的那个毫秒差 (数字格式 不能是字符串)var timeBox = document.getElementById('timeBox');
function computed() {
var nowTime = new Date();
var targeTime = new Date("2017/10/22 17:00:00");
var spanTime = targeTime - nowTime;
if(spanTime <=0) {
timeBox.innerHTML = '开始考试';
window.clearInterval(timer);
return;
}
var hour = Math.floor(spanTime/(1000*60*60));
spanTime -= hour*60*1000;
var minute = Math.floor(spanTime/(1000*60));
spanTime -= minute*60*1000;
var second = Math.floor(spanTime/1000);
hour < 10 ? hour = '0'+ hour:null;
minute<10?minute = '0'+ minute :null;
second < 10 ?second = '0' + second :null;timeBox.innerHTML = hour + ':' + minute + ':' + second;
}
var timer = window.setInterval(computed,1000);
复制代码
- 动力: 这是我的学习笔记(来源于视频或者查阅文档),您能从中得到收获和进步,是我分享的动力,帮助别人,自己也会更快乐
- 期望: 不喜勿喷,谢谢合作!如果涉及版权请及时联系我,马上删除!