四周

105 阅读13分钟

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

ES5:提供了一些新的API
1、四大特性可以保护对象:
  对象的每一个属性都要4大特性,3个开关默认为ture
  {
    value:1001,//保存实际值的地方
    writable:true//开关:控制属性是否可以被修改
    enumerable:ture,//开关:控制属性是否可以被for in 循环遍历
    configurable:false//开关:控制属性是否可以被删除,总开关,一旦设置为false就不会允许修改其他特性,它本身一旦改为false不可逆
   }
三个级别:
1、防扩展:防添加
  Object.prevenExtensions(obj);
2、密封:防添防删除
  Object.seal(obj);
3、冻结:防添加防删除防修改
  Object.freeze(obj);
不推荐使用
1、如果是使用面向过程开发,保护不了(保护个毛)
2、前辈也没有保护,没有保护的必要



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

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

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

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

	
   2、修改对象的某个属性的四大特性:
	Object.defineProperties(obj,{
		"属性名":{四大特性},
		...
	})
复制代码
	1、如果以后你使用面向过程开发,保护个毛啊
	2、前辈们都没有保护,你保护个毛啊
复制代码

2、*****数组的新的API:3组6个

1、判断: 判断数组中的元素是否满足我们的条件
	1、every:判断数组中的元素是否【都】满足我们的条件,类似于我们的&&,只要有一个为false则为false
	2、some:判断数组中的元素是否【包含】满足我们的条件,类似于我们的||,只要有一个为true则为true
	语法: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、汇总和过滤:

  • 3.1、过滤:筛选出符合条件的元素: - 不会修改原数组

    var subArr=arr.filter(function(val,i,arr){
            return 判断条件;
    })
    复制代码
    
  • 3.2、汇总:将所有的数组的元素进行+-*/

    var sum=arr.reduce(function(prev,val,i,arr){
        return prev+val;
    },base)
    复制代码
    

总结 : 以上6个API简化for循环

3、
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数组,不能遍历对象(其实可以需要多加一句话)
复制代码

1.Browser Object Model(浏览器对象模型)

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

2、BOM对象:

  1. window(定时器)---重点
  2. history、
  3. location、---重点
  4. navigator
  5. event---重点
  6. screen...

3、window对象:扮演了2个角色:

1、浏览器中,window代替了ES的Global充当全局作用域;包含了所有的全局对象、变量、函数

2、指代当前浏览器的窗口

3.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>
复制代码

注: 页面跳转时注意考虑用户体验感

3.2、window对象:属性和方法:

属性:

获取浏览器窗口的大小:

  1. 文档显示区域的大小:body部分

       innerWidth/innerHeight
    复制代码
    
  2. 完整的浏览器大小:

    outerWidth/outerHeight
    复制代码
    
  3. 屏幕的大小:没用 - 桌面应用才用的

    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);
复制代码

小结 : 两种定时器底层相同,可以互换,你爱用哪个就用哪个

完整的DOM总结增,删,改,查

增:

  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、直接找:

按照HTML特点查找

  document.getElementsByTagName("标签名")
  document.getElementName("name值")
  document.getElementsByClassName("class名")  
复制代码

按照CSS选择器进行查找

  document.querySelectorAll
  document.querySelector
复制代码
面试题

getXXX和querySelectXXX的区别:

  • 返回的结果不同

    getXXX:返回的是一个动态集合
         ---------每次修改DOM树,都会悄悄的再次查找;
         
    querySelectXXX:返回的是一个静态集合
         ---------每次修改DOM树不会再次查找,至关第一次找出的结果
    复制代码
    
  • 集合类型

    动态集合:支持forEach
    
    静态集合:不支持forEach
    复制代码
    
  • 复杂查找时

    尽量使用varelem = document.querySelectAll("任意的CSS选择器")
    复制代码
    

- 2、通过节点关系查找

前提 : 至少要先找到一个元素

  1.  父元素:xx.parentNode
    复制代码
    
  2.  子元素:xx.children
    复制代码
    
  3.  第一个儿子:firstElementChild
    复制代码
    
  4.  最后一个儿子:lastElementChild
    复制代码
    
  5.  前一个兄弟:previouseElementSibling
    复制代码
    
  6.  最后一个兄弟:nextElementSibling
    复制代码
    

- 3遍历层级不明确的树状结构:

区别:

  1.   递归(不仅可以遍历元素、还可以遍历数据)
    复制代码
    

函数中再一次调用函数自己,但是迟早会执行完之后会停下来

作用:专门用于遍历层级不明确的树状结构

算法:使用深度优先遍历

实现:2步

   1.创建函数:传入实参树根,形参接住,直接要做第一层要做的操作
   function f1(root){
       //直接要做的第一层的操作
       //判断自己是否有下一级,如果还有下一级,接着又调用此方法,但是传入的实参已经变成你的下一级
   }
   
   2.调用函数f1()
   fi(实参);
复制代码
  1.   遍历API
    复制代码
    

作用:专门用于遍历层级不明确的树状结构

算法:使用深度优先遍历

实现:2步

    1创建treeWalker对象
    var tw=document.createTreeWalker(ul,NodeFilter.SHOW_ELEMENT[所有元素节点]/SHOW_ALL[所有的节点])
    2.反复调用nextNode方法
    while()(node=tw,textNode())!=null){
         node;//当前节点做什么操作
    }
复制代码

注意:此方法必须跳过起点

  1.   纯循环 遍历层级不明确的树状结构的时候-----别用
    复制代码
    

总结

  • 遍历API(在遍历页面元素的时候)
  • 纯循环难度较大,尽量别使用,可以锻炼一下逻辑
  • 遇到层级不明确的树状结构的时候优先使用递归(不仅可以遍历元素,还可以遍历数据)

2、内容:

  1. 一切的获取往往都是用于判断
    复制代码
    
  2. 一切的设置,说白了就是在做修改操作
    复制代码
    

区别:

  1. elem.innerHTML:可以识别标签,再使用判断的时候要注意
  2. textContent:不能识别标签,而且具有兼容性问题(老版)
  3. elem.innerText:没有兼容性问题,不识别标签
  4. elem.value:用于操作input和select标签

3、属性:

核心DOM

获取: elem.getAttribute("属性名"); 
设置: elem.setAttribute("属性名","属性值");
复制代码

简化版

获取:elem.属性名;
设置:elem.属性名="属性值"
复制代码

简化版注意:

  • class类必须写为className
  • 只能操作标准属性,不能操作自定义属性

4、样式:

//只能获取内联样式

  elem.style.css属性名;
  elem.style.css属性名="属性值"
复制代码

注意:

  • 优先级除了(!important)最高,保证js用户触发式一定生效
  • 不会牵一发而动全身,只会操作当前元素

缺点 : 获取样式时必须保证此样式在内联样式之中

特殊:CSS属性名写法,如果有"-"(横线)要去掉横线,变为小驼峰命名法


新增方法

1、属性:

  • 删除:

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

    2.HTML DOM:elem.属性名="";-----赋值为空,删不干净,属性值确实没有了,但是属性名还在,有的属性值有属性名也是具有效果的比如:(href,disable,selected)

  • 判断有没有:elem.hasAttribute("属性名"); -- 只能判断有没有不能判断具体值是什么

  • 推荐:

     if(elem.getAttribute("属性名")=="值"){
     
     }
    复制代码
    

2、样式:

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

3、渲染页面:3种:

  1. 父元素.appendChild(新元素);//新元素会插入到父元素的末尾-----重点
  2. 父元素.insertBefore(新元素,已有子元素)//新元素会插入到父元素里面已有子元素之前---不推荐,会影响修改其他人的下标

3.父元素.replaceChild(新元素,已有子元素)//新元素会替换掉父元素里面的已有的子元素

 删除元素:elem.remove();
复制代码

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

- 1、image:

  var img=new Image();
复制代码

- 2、form:简化了查找

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

- 3、select:

  1、options===(等效于)children//获取到select下面所有的option
  2、selectedIndex === 获取当前选中项的下标-------只要做联动必不可少
  3add()
      select.add.(option)---完全等效于appendChild,追加元素
  4remove(i) === 删除下标为i的option
  5、onchange:专属事件----选中项发生改变时触发
复制代码

- 4、option:

  select.add(new Option("innerHTML","value"))