ES5&ES6、操作元素的归纳以及BOM的简单介绍

251 阅读15分钟

ES5&ES6

ES:ECMAScript:核心语法:升级 -> 操作简化

一、ES5:提供了一些新的API

1、保护对象:保护对象的属性和方法

(1)四大特性可以保护对象:

1、对象的每一个属性都要4大特性,3个开关默认为true

{
  value: 1001,//保存实际值的地方
  writable: true,//开关:控制属性是否可以被修改 
  enumerable: true,//开关:控制属性是否可以被for in循环遍历
  configurable: false//开关:控制属性是否可以被删除,总开关,
                            一旦设置为false就不会允许修改其他特性,
                             它本身一旦改为false不可逆
}

	

2、修改对象的某个属性的四大特性:

	Object.defineProperties(obj,{
		"属性名":{四大特性},
		...
	})
(2)三个级别:

1、防扩展:防添加:Object.preventExtensions(obj);

2、密封:防添加防删除:Object.seal(obj)

3、冻结:防添加防删除防修改:Object.freeze(obj);

个人不推荐:前辈们都没有保护
	

2、*****数组的新的API:3组6个 (6个API简化for循环):

every、some、forEach、map、reduce、filter
(1)判断:判断数组中的元素是否满足我们的条件

1、every:判断数组中的元素是否【都】满足我们的条件,类似于我们的&&;

2、some:判断数组中的元素是否【包含】满足我们的条件,类似于我们的||;

	语法:arr.every/some(function(val,i,arr){
			//val:当前值
			//i:当前值的下标
			//arr:数组本身
			//虽然提供了3个形参,但是到底要用几个看我们自己
			//切忌:函数自带return undefined;
			return 判断条件;
	      })
(2) 遍历:把数组中的每个元素取出来执行相同 或 相似的操作

1、*****forEach:

         直接修改原数组
		arr.forEach(function(val,i,arr){
			直接写操作;
	        })

2、*map:不修改原数组,直接返回新数组

		var newArr=arr.map(function(val,i,arr){
			return 直接写操作;
	        })

3、汇总和过滤:ruduce/filter

	1、过滤:筛选出符合条件的元素: - 不会修改原数组
		var subArr=arr.filter(function(val,i,arr){
			return 判断条件;
	      	})
	

	2、汇总:将所有的数组的元素进行+-*/
		var sum=arr.reduce(function(prev,val,i,arr){
			return prev+val;
	      	},base)

3、var 子对象
 var 子对象=Object.create(父对象,{
           "属性名":{四大特性},
            ...
        }) - 根据一个父对象创建一个子对象并且继承已经设置完毕,提前保护对象
4、*****call/apply/bind:替换了函数中的this
(1)call/apply:临时替换了函数中的this - 借
	差别:call:要求传入的实参必须单独传入
	      apply:要求传入的实参必须整理为一个数组,只能传一个数组参数
	强调:call/apply相当于立刻调用函数
	用法:方法名.call(借用的对象,实参,...)
	      方法名.apply(借用的对象,[实参,...]) - apply自动打散数组

	固定套路:
	      Object.prototype.toString.call/apply(数组)
	      Math.max/min.apply(Math,arr);
	      *关键点:将类数组转为普通数组
	      lis=Array.prototype.slice.call(lis);
(2)bind:永久替换了函数中的this - 买
	 3件事
	 1、创建了一个函数功能和原函数完全一样
	 2、将新函数的this永久绑定为了你指向的对象
	 3、将信函书中的部分固定参数提前永久绑定	

	 用法:var 新方法名=方法名.bind(永久绑定的对象,永久绑定的实参,...);
	       不会立刻执行,需要我们程序员手动调用

个人建议:如果你的这方法要经常反复使用,可以使用bind - 买
	 *如果你需要一个方法立刻就要执行,建议call/apply - 借

5、严格模式:很严格

开启严格模式:"use strict"; - 可以出现在任何作用域的顶部
用处:
  1、禁止给未声明的变量进行赋值
  2、将静默失败升级为错误

二、*****ES6:简化了/改变了语法:

1、模板字符串:支持直接在字符串中书写变量

`我的名字叫${name}`
再也不用""''

2、块级作用域:将var替换为let用于创建变量:优先使用let

作用:
  1、let之前不允许出现未声明的同名变量
	- 解决声明提前
  2、添加了块级作用域:
	一个{}就是一个块
  3、*绑定事件时,会记录着当前元素的下标
	不需要自己定义自定义下标

3、箭头函数:简化一切的回调函数

回调函数:匿名函数,没有自调,就是回调
公式:去掉function,()和{}之间添加=>,
         如果形参只有一个省略(),如果函数体只有一句话省略{},
         如果函数体只有一句话并且是return,{}和return都省略
         

箭头函数中如果出现this->外部的对象

4、for...of循环 - 不建议使用

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

缺点:
  1、不能直接修改原数组,只能返回新数组
  2、不能遍历hash数组,不能遍历对象(其实可以需要多加一句话)
                
      

找元素

一、DOM概念:Document Object Model

      提供了专门用于操作HTML文档的API
          
 DHTML:动态的HTML,一切实现网页动态效果的技术的统称,并不是什么新技术、新概念,仅仅只是一个统称
	HTML+CSS+JS(DOM)

 面试/笔试:HTML/XHTML/DHTML/XML:
HTML:网页
XHTML:更严格的网页
DHTML:动态的网页
XML:数据格式

 DHTML模型:
DOM:见上面
     W3C标准

BOM:Browser Object Model

提供专门用于操作浏览器的API
没有标准,但是大部分浏览器厂商已经统一的实现了,除了老IE,具有大量的兼容性问题,
使用的较少(重点:定时器、event事件)

DOM:本来是可以操作一切结构化文档(HTML/XML)的:3部分

1、核心DOM:万能!但是API比较繁琐:elem.setAttribute("属性名","属性值")
2HTML DOM:只能操作HTML文档,API非常的简单:elem.属性名=值;
3XML DOM:垃圾,因为XML基本已经淘汰很多年了
建议:以后优先使用HTML DOMHTML DOM实现不了,在用核心DOM补充

二、***DOM树:保存所有网页内容的树状结构:

树根:document,不需要创建,由浏览器的js解释器自动创建,一个页面只有一个树根

DOM节点/对象/元素:一个标签、文本、属性、注释等等

每个DOM节点/对象/元素都有三大属性:

1、xx.nodeType:获取xx的节点类型
		document:9
		元素标签:1
		文本节点:3
		属性节点:2
		对于现在的开发者,没用
2、属性节点.nodeValue:获取属性节点的节点值
现在依然没用:我们现在用getAttribute("")能直接获取到属性的值
3、***xx.nodeName:获取属性节点的名称:
		我直接找儿子的话,可能找到多种标签,但是我们希望对不同的标签执行不同的操作
		特殊:获取出来的标签都是全大写
三、通过 节点之间关系 获取元素:
1、父:elem.parentNode;
2、子:elem.children; - 集合:只能找到儿子级
3、第一个儿子:elem.firstElementChild;
4、最后一个儿子:elem.lastElementChild;
5、前一个兄弟:elem.previousElementSibling;
6、后一个兄弟:elem.nextElementSibling;

四、*****递归:函数中,再一次调用函数自己,但迟早有一天要让他停下来

   作用:专门用于【遍历层级不明确的树状结构】
   如何实现:2步
1、创建函数,传入实参树根,形参接住,直接做第一层要做的操作
function f1(root){
	        直接做第一层要做的操作
               //判断自己有没有下一级,如果有再次调用此方法,但传入的实参已经变成了你的下一级
}
2、调用函数
f1(实际的根元素)		

 算法:深度优先!优先遍历当前节点的子节点
       子节点遍历完,才会跳到兄弟节点

递归:优点:直观,易用
      缺点:效率较低,同时开启的函数很多,占用内存空间,不是任何时候都要使用  
          ---几乎不担心(【遍历层级不明确的树状结构】)
循环:优点:效率较高
	 缺点:难度极大!

五、遍历API:专门用于【遍历层级不明确的树状结构】

2步:

1、创建treewalker对象
	var tw=document.createTreeWalker(root,NodeFilter.SHOW_ALL/SHOW_ELEMENT);
2、反复调用nextNode方法:
	while((node=tw.nextNode())!=null){
		node;//当前节点做什么操作
	}

深度优先算法
注意:此方法必须跳过起点

六、纯循环遍历层级不明确的树状结构 - 几乎不会怎么使用

总结:以后不用遍历API(只能遍历页面元素),也不用纯循环(难度大),
        遇到层级不明确的时候,使用递归(不仅遍历元素,还能遍历数据)

七、***查找元素:

1、按照HTML的特点去查找元素:4个

var elem=document.getElementById("id");

	找到了是单个元素,没找到一定是null

var elem=document.getElementsByTagName/ClassName/Name("标签/class名/name值")

	找到了是个集合,没找到一定是一个空集合[]

2、按照CSS选择器进行查找:2个

(1)单个元素,没找到一定是null,如果有多个,也只会找到第一个

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

(2)多个元素:找到的是一个集合,没找到空集合

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

面试题:getXXX和querySelectXXX的区别?

1、返回结果不同:

getXXX - 返回是一个动态集合(每次DOM树修改,都会悄悄的再次查找)
querySelectXXX - 返回是一个静态集合 (每次DOM树修改,不会再次查找,只管第一次找到的结果)

2、动态集合,不支持forEach 静态集合,支持forEach

3、复杂查找时,尽量使用var elem=document.querySelectorAll("任意css选择器")

操作元素归纳(1)

1、*内容:

1、innerHTML:支持标签,并且没有兼容性问题

获取:elem.innerHTML;
设置:elem.innerHTML="新值";

2、textContent:不支持标签,并且有兼容性问题,老IE:innerText,只不过小三上位(老IE不支持textContent,主流浏览器都支持innerText) 获取:elem.innerText; 设置:elem.innerText="新值";

3、value:转为input、select准备的

获取:elem.value;
设置:elem.value="新值";

2、*属性:

获取属性值: 核心DOM:万能的,可以操作一切属性 elem.getAttribute("属性名");

HTML DOM:只能操作标准属性,并且class需要写出className
	elem.属性名;

设置属性值: 核心DOM:万能的,可以操作一切属性 elem.setAttribute("属性名","值");

HTML DOM:只能操作标准属性,并且class需要写出className
	elem.属性名="新值";

删除属性: *核心DOM:elem.removeAttribute("属性名"); - 删干净整个属性节点

HTML DOM:elem.属性名=""; 
    - 赋值为空,删不干净,属性值确实没了,但属性名还在,有的属性只需要属性名也具有效果
    (href、disabled、readonly

判断属性:只能判断有没有
核心DOM:elem.hasAttribute("属性名");

个人更推荐:if(a1.getAttribute("属性名")=="属性值"){
		console.log("有并且是");
	    }

3、样式:

内联:优先级最高,只会操作某个元素,不会牵一发动全身

  获取:elem.style.css属性名;
  设置:elem.style.css属性名="css属性值";
	css属性名如果有横线,去掉横线写为小驼峰命名法

样式表:4步

		//获取哪一个样式表
		var sheet=document.styleSheets[1];
		//获取所有的样式规则
		var rules=sheet.cssRules;
		//获取到了我想要操作的样式规则
		var rule=rules[36];
		//修改或获取样式
		console.log(rule.style.background);
		rule.style.background="purple";

一切的获取都是为了判断比较 一切的设置都是在做修改操作

4、创建元素&渲染页面&删除元素:

(1)创建元素:3步

1、var 空标签=document.createElement("标签名");

2、设置必要的属性或事件

	空标签.属性名="值"
	空标签.on事件名=function(){
		操作
	}

3、渲染页面元素:3种

*父元素.appendChild(新元素);//新元素会插入到父元素里面的末尾
父元素.insertBefore(新元素,已有子元素);//新元素会插入到父元素里面的已有子元素之前 - 
       不推荐:修改其他的人下标
父元素.replaceChild(新元素,已有子元素);//新元素会替换掉父元素里面的已有子元素

4、删除元素:元素.remove();

核心DOM学习完毕:已经无敌了 - 增 删 改 查:元素、内容、属性、样式
(2)HTML DOM提供了一些常用对象:简化了核心DOM的操作:但是不是人人都能简化

1、image:简化了创建

   	var img=new Image();
   强调:在DOM中,不是人人都具有构造函数创建方式,只有我讲到的人才有

2、form:简化了查找

   查找form元素:var form=document.forms[i];
   查找表单控件:var input=form.elements[i];
   专属事件:onsubmit事件 -> 提交的一瞬间会执行,也可以阻止提交return false;

3、*select:属性:2个

	  1、options === children:获取到select下面的所有的option
	  2、*selectedIndex - 获取到当前选中项的下标,只要是做联动,必不可少

	方法:
	  1、*select.add(option) - 完全等效于appendChild,追加元素
	  2select.remove(i); - 删除select中的第i个option

	专属事件:onchange-> 选中项发生改变时触发

4、*option:简化了创建 var opt=new Option("innerHTML","value");

操作元素归纳(2)

增:

1、元素:3步

1、var elem=document.createElement("标签名");
2、elem.属性名="属性值"
   elem.on事件名=function(){}
3、父.appendChild(elem);
   父.insertBefore(elem,已有子元素);
   父.replaceChild(elem,已有子元素);

2、内容:elem.innerHTML/innerText/value+="新内容"

3、属性:elem.setAttribute("class","d1 d2");

4、样式:elem.style.css属性名="css属性值";//没有叫添加,有了叫替换

删:

1、元素:elem.remove();

2、内容:elem.innerHTML/innerText/value=""

3、属性:elem.removeAttribute("属性名");

4、样式:elem.style.css属性名="";//没有叫添加,有了叫替换

改:

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

2、内容:elem.innerHTML/innerText/value="新值"

3、属性:elem.setAttribute("class","d2");

4、样式:elem.style.css属性名="css属性值";//没有叫添加,有了叫替换

查:

1、元素:

1、直接找:
	document.getXXX
	document.querySelectorXXX

2、通过关系查找

3、层级不明确:递归(元素、数据)、遍历API、纯循环	

2、内容:elem.innerHTML/innerText/value;

3、属性:elem.getAttribute("属性名");

4、样式:elem.style.css属性名;//只能获取内联样式

拓展:

1、属性:

删除:
判断有没有:elem.hasAttribute("属性名"); -- 只能判断有没有不能判断具体值是什么
推荐:	    if(elem.getAttribute("属性名")=="值"){

	    }

2、样式:

样式表:
  获取:document.styleSheets[i].cssRules[i].style.css属性名
  设置:document.styleSheets[i].cssRules[i].style.css属性名="css属性值"

3、渲染页面:3种:最推荐appendChild 删除元素:

4、HTML DOM常用对象:个别可以简化

1、image:var img=new Image();

2formvar form=document.forms[i]
	var input=form.elements[i]
	onsubmit

3、select:
	1、options===children
	2、selectedIndex === 获取当前选中项的下标
	3、add()
	4、remove(i) === 删除下标为i的option
	5、onchange

拓展:

1、str.trim();//去掉字符串的开头结尾的空白字符

2、var bool=confirm("提示文字");

 //用户确认框:
用户点击确定->true   
用户点击取消->false
    
    
    
    
    

BOM

1、BOM:Browser Object Model

浏览器  对象   模型
提供了专门用于操作浏览器的API - 没有标准,使用的较少,但大部分浏览器厂商已经统一实现了(老IE)

2、BOM对象:*window(定时器)、history、*location、navigator、*****event、screen...

3、window对象:

         扮演了2个角色:
	1、浏览器中,window代替了ES的Global充当全局作用域
		包含了所有的全局对象、变量、函数
	2、指代当前浏览器的窗口
(1)*网页打开新链接的方式

提升用户的体验感:

1、替换当前页面,可以后退:

		HTML:<a href="url">文字</a>
		  JSopen("url","_self");

2、替换当前页面,禁止后退:使用场景:电商网页:结账完毕后,不允许用户后退

		history对象:保存了当前窗口的历史记录,功能:前进后退
		location:保存了当前窗口正在打开的url
		location.replace("新url");//替换当前网址、不会产生历史记录

3、在新窗口打开,可以打开多个:

		HTML:<a href="url" target="_blank">文字</a>
		  JS:open("url","_blank");

4、在新窗口打开,只能打开一个:使用场景:电商网页:跳转到 支付结账页面,只允许用户打开一个

		HTML:<a href="url" target="自定义">文字</a>
		  JS:open("url","自定义");
		自定义:窗口的底层都有一个名字,如果出现重复的名字则新窗口会替换掉原来的旧窗口
扩展:a标签可以做的事?
1、跳转      
2、锚点 
3、下载:<a href="xx.rar/zip/exe">文字</a>   
4、打开图片、txt:<a href="xx.图片后缀/txt">文字</a>
5、直接书写js:<a href="javascript:js代码;">文字</a>
                    
<a href="https://www.baidu.com">替换当前,可后退</a>
<div id="d1">替换当前,可后退</div>
	
<a href="https://www.baidu.com" target="_blank">新窗口,可打开多个</a>
<div id="d2">新窗口,可打开多个</div>
	
<a href="https://www.baidu.com" target="dy">新窗口,只能打开一个</a>
<div id="d3">新窗口,可打开多个</div>
	
<div id="d4">替换当前,禁止后退</div>
	
<script type="text/javascript">
		d1.onclick=function(){
			open("https://www.baidu.com","_self");
		}
		
		d2.onclick=function(){
			open("https://www.baidu.com","_blank");
		}
		
		d3.onclick=function(){
			open("https://www.baidu.com","dls");
		}
		
		d4.onclick=function(){
			location.replace("https://www.baidu.com")
		}
</script>     
                                    
(2) window对象:属性和方法:

属性:

获取浏览器窗口的大小:
	        文档显示区域的大小:body部分
		innerWidth/innerHeight

完整的浏览器大小:
		outerWidth/outerHeight
		屏幕的大小:没用 - 桌面应用才用的
		screen.width/height

方法:

1、打开新窗口:var newW=open("url","自定义name","width=,height=,left=,top=");
   特殊:如果没传入第三个参数,新窗口会和浏览器并为一体
   如果传入第三个参数,新窗口会脱离浏览器
   建议宽高不小于200
   有可能会被浏览器拦截
   
2、关闭窗口:窗口.close();
3、修改窗口的大小:新窗口.resizeTo(newW,newH);
4、修改窗口的位置:新窗口.moveTo(x,y);

扩展:获取鼠标的坐标:
(1)事件中传入一个形参e->获得到事件对象event(其中一个作用获取鼠标的坐标)
(2) 获取:
       e.screenX/Y;//相对于屏幕
       e.clientX/Y;//相对于浏览器客户端
          *e.pageX/Y;//相对于网页的

鼠标跟随效果:关键点:
		(1) 绑定事件:window.onmousemove
		(2) 图片位置一定和鼠标位置一起
		(3) 图片的加载速度比js的执行速度要慢,
                    img.onload=function(){
					//最后才会执行
		     }

5、*****定时器:2种
	(1)周期性定时器:先等待,在执行一次,在等待,在执行一次...
			开启:timer=setInterval(callback,间隔毫秒数);
			停止:clearInterval(timer);

	(2)一次性定时器:先等待,在执行一次,结束
			开启:timer=setTimeout(callback,间隔毫秒数);
			停止:clearTimeout(timer);

		两种定时器底层相同,可以互换