ES5
ES5:提供了一些新的API
保护对象
保护对象:保护对象的属性和方法
四大特性可以保护对象:
- 对象的每一个属性都要4大特性,3个开关默认为
true
举例:
{
value: 1001,//保存实际值的地方
writable: true,//开关:控制属性是否可以被修改
enumerable: true,//开关:控制属性是否可以被for in循环遍历
configurable: false//开关:控制属性是否可以被删除,总开关,一旦设置为false就不会允许修改其他特性,它本身一旦改为false不可逆
}
- 修改对象的某个属性的四大特性:
语法:
Object.defineProperties(obj,{
"属性名":{四大特性},
...
})
三个级别:
-
防扩展:防添加 语法:
Object.preventExtensions(obj); -
密封:防添加防删除 语法:
Object.seal(obj); -
冻结:防添加防删除防修改 语法:
Object.freeze(obj);
新增数组API
数组的新的API:6个
判断
判断:判断数组中的元素是否满足条件
- every:判断数组中的元素是否全部满足我们的条件,类似于
&&,只要有一个为false则为false - some:判断数组中的元素是否【包含】满足我们的条件,类似于我们的||,只要有一个为
true则为true
语法:
arr.every/some(function(val,i,arr){
//val:当前值
//i:当前值的下标
//arr:数组本身
//虽然提供了3个形参,但是到底要用几个看我们自己
//切忌:函数自带return undefined;
return 判断条件;
})
遍历
遍历:把数组中的每个元素取出来执行相同 或 相似的操作
- forEach:直接修改原数组
语法:
arr.forEach(function(val,i,arr){
直接写操作;
})
- map:不修改原数组,直接返回新数组
语法:
var newArr=arr.map(function(val,i,arr){
return 直接写操作;
})
汇总和过滤:
- 过滤:筛选出符合条件的元素: - 不会修改原数组
语法:
var subArr=arr.filter(function(val,i,arr){
return 判断条件;
})
- 汇总:将所有的数组的元素进行
+-*/
语法:
var sum=arr.reduce(function(prev,val,i,arr){
return prev+val;
},base)
创建子对象
根据一个父对象创建一个子对象并且继承已经设置完毕,提前保护对象
语法:
var 子对象=Object.create(父对象,{
"属性名":{四大特性},
...
})
call/apply/bind
call/apply/bind:替换了函数中的this
-
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);
- 差别:
-
bind:永久替换了函数中的this(买)
-
注意:
- 创建了一个函数功能和原函数完全一样
- 将新函数的this永久绑定为了你指向的对象
- 将新函数中的部分固定参数提前永久绑定
-
用法:
var 新方法名=方法名.bind(永久绑定的对象,永久绑定的实参,...);
-
强调:新方法不会立刻执行,需要手动调用
-
-
使用场景:
- 如果你的这方法要经常反复使用,可以使用bind - 买
- 如果你需要一个方法立刻就要执行,建议call/apply - 借
严格模式
- 开启严格模式:
"use strict";(可以出现在任何作用域的顶部) - 用处:
- 禁止给未声明的变量进行赋值
- 将静默失败升级为错误
ES6
ES6:简化了(改变了)语法
模板字符串
模板字符串:支持直接在字符串中书写变量
我的名字叫${name},可以代替""和''
举例:
var a=3,b=5;
console.log(`${a}+${b}的结果为${a+b}`);
块级作用域
块级作用域:将var替换为let用于创建变量:优先使用let
作用:
- let之前不允许出现未声明的同名变量(解决声明提前)
- 添加了块级作用域(一个
{}就是一个块) - 绑定事件时,会记录着当前元素的下标(不需要自己定义自定义下标)
箭头函数
箭头函数:简化一切的回调函数
回调函数:匿名函数,没有自调,就是回调
公式:去掉function,()和{}之间添加=>,如果形参只有一个省略(),如果函数体只有一句话省略{},如果函数体只有一句话并且是return,{}和return都省略
注意:
-
箭头函数中如果出现this->外部的对象
-
建议在事件中暂时不要简化为箭头函数
for...of循环
语法:
for(var v of arr){
v;//当前值
}
缺点:
- 不能直接修改原数组,只能返回新数组
- 不能遍历hash数组,不能遍历对象(其实可以需要多加一句话)
DOM
DOM概念:Document Object Model,提供了专门用于操作HTML文档的API
DHTML
DHTML:动态的HTML,一切实现网页动态效果的技术的统称,并不是什么新技术、新概念,仅仅只是一个统称,HTML+CSS+JS(DOM)
面试/鄙视题:HTML/XHTML/DHTML/XML分别是什么:
HTML:网页
XHTML:更严格的网页
DHTML:动态的网页
XML:数据格式
DHTML模型:
- DOM:Document Object Model(W3C标准)
- BOM:Browser Object Model,提供专门用于操作浏览器的API(没有标准,但是大部分浏览器厂商已经统一的实现了,除了老IE,具有大量的兼容性问题,使用的较少(重点:定时器、event事件))
DOM
DOM:可以操作一切结构化文档(HTML/XML):3部分
- 核心DOM:万能!但是API比较繁琐:elem.setAttribute("属性名","属性值")
- HTML DOM:只能操作HTML文档,API非常的简单:elem.属性名=值;
- XML DOM:XML基本已经淘汰很多年了 建议:以后优先使用HTML DOM,HTML DOM实现不了,在用核心DOM补充
DOM树
DOM树:保存所有网页内容的树状结构
树根:document,不需要创建,由浏览器的js解释器自动创建,一个页面只有一个树根
DOM节点/对象/元素:一个标签、文本、属性、注释等等
每个DOM节点/对象/元素都有三大属性:
-
xx.nodeType:获取xx的节点类型- document:9
- 元素标签:1
- 文本节点:3
- 属性节点:2
-
属性节点.nodeValue:获取属性节点的节点值- 现在没用:现在用getAttribute("")能直接获取到属性的值
-
xx.nodeName:获取属性节点的名称:- 找到多个子元素,但是我们希望对不同的子元素执行不同的操作
- 特殊:获取出来的标签都是全大写
通过节点之间关系获取元素
- 父:elem.parentNode;
- 子:elem.children;(集合:只能找到儿子级)
- 第一个儿子:elem.firstElementChild;
- 最后一个儿子:elem.lastElementChild;
- 前一个兄弟:elem.previousElementSibling;
- 后一个兄弟:elem.nextElementSibling;
递归
递归:函数中,再一次调用函数自己,最后一定要结束 使用场景:用于【遍历层级不明确的树状结构】 使用步骤:2步
- 创建函数,传入实参树根,形参接住,直接做第一层要做的操作
语法:
function f1(root){
//直接做第一层要做的操作
//判断自己有没有下一级,如果有再次调用此方法,但传入的实参已经变成了你的下一级
}
- 调用函数
语法:
f1(实际的根元素)
算法:深度优先!优先遍历当前节点的子节点,子节点遍历完,才会跳到兄弟节点
递归、循环比较
- 递归:
- 优点:直观,易用
- 缺点:效率较低,同时开启的函数很多,占用内存空间,不是任何时候都要使用 - 几乎不担心(【遍历层级不明确的树状结构】)
- 循环:
- 优点:效率较高
- 缺点:难度极大!
遍历API
遍历API:专门用于遍历层级不明确的树状结构 使用步骤:2步
- 创建treewalker对象
语法:
var tw=document.createTreeWalker(root,NodeFilter.SHOW_ALL/SHOW_ELEMENT);
//SHOW_ALL查找全部,SHOW_ELEMENT查找元素
- 反复调用nextNode方法
语法:
while((node=tw.nextNode())!=null){
node;//当前节点做什么操作
}
算法:深度优先算法
注意:此方法必须跳过起点
纯循环遍历层级不明确的树状结构
举例:
html:
<ul id="ul">
<li>电影</li>
<li>动漫
<ul>
<li>剑风传奇</li>
<li>海绵宝宝</li>
<li>哆啦A梦</li>
</ul>
</li>
<li>剧集
<ul>
<li>剑风传奇</li>
<li>海绵宝宝</li>
<li>哆啦A梦</li>
</ul>
</li>
</ul>
js:
function getChildes(root){
var org=root;//org=ul
while(true){
root.style.border="1px solid #000";
if(root.firstElementChild){
root=root.firstElementChild
}else if(root.nextElementSibling){
root=root.nextElementSibling
}else{//没有儿子,也没有下一个兄弟
while(!root.parentNode.nextElementSibling&&root!=org.lastElementChild){
root=root.parentNode;
}
root=root.parentNode.nextElementSibling;
if(root==org.lastElementChild){
root.style.border="1px solid #000";
break;
}
}
}
}
getChildes(ul);
总结:以后不用遍历API(只能遍历页面元素),也不用纯循环(难度大),遇到层级不明确的时候,使用递归(不仅遍历元素,还能遍历数据)
查找元素
- 按照HTML的特点去查找元素:4个 语法:
var elem=document.getElementById("id");(找到了是单个元素,没找到一定是null)var elem=document.getElementsByTagName/ClassName/Name("标签/class名/name值");(找到了是个集合,没找到一定是一个空集合[])
- 按照CSS选择器进行查找:2个
- 单个元素,没找到一定是null,如果有多个,也只会找到第一个
- 语法:
var elem=document.querySelector("任意css选择器");
- 语法:
- 多个元素:找到的是一个集合,没找到空集合
- 语法:
var elem=document.querySelectorAll("任意css选择器");
- 语法:
面试题:getXXX和querySelectXXX的区别?
1、返回结果不同:
getXXX - 返回是一个动态集合(每次DOM树修改,都会悄悄的再次查找)
querySelectXXX - 返回是一个静态集合 (每次DOM树修改,不会再次查找,只管第一次找到的结果)
2、动态集合,不支持forEach
静态集合,支持forEach
3、复杂查找时,尽量使用var elem=document.querySelectorAll("任意css选择器")
操作元素
操作内容
-
innerHTML:支持标签,并且没有兼容性问题
- 获取:elem.innerHTML;
- 设置:elem.innerHTML="新值";
-
textContent:不支持标签,并且有兼容性问题(老IE:innerText,老IE不支持textContent,主流浏览器都支持innerText)
- 获取:elem.innerText;
- 设置:elem.innerText="新值";
-
value:专为input、select准备的
- 获取:elem.value;
- 设置:elem.value="新值";
操作属性
-
获取属性值:
-
核心DOM:万能的,可以操作一切属性
- 语法:
elem.getAttribute("属性名");
- 语法:
-
HTML DOM:只能操作标准属性,并且class需要写出className
- 语法:
elem.属性名;
- 语法:
-
-
设置属性值:
-
核心DOM:万能的,可以操作一切属性
- 语法:
elem.setAttribute("属性名","值");
- 语法:
-
HTML DOM:只能操作标准属性,并且class需要写出className
- 语法:
elem.属性名="新值";
- 语法:
-
-
删除属性:
- 核心DOM:删干净整个属性节点
- 语法:
elem.removeAttribute("属性名");
- 语法:
- HTML DOM:赋值为空,删不干净,属性值确实没了,但属性名还在,有的属性只需要属性名也具有效果(href、disabled、readonly)
- 语法:
elem.属性名="";
- 语法:
- 核心DOM:删干净整个属性节点
-
判断属性:
- 核心DOM:只能判断有没有
- 语法:
elem.hasAttribute("属性名");
- 语法:
- 推荐:使用getAttribute
- 语法:
if(a1.getAttribute("属性名")=="属性值"){console.log("有并且是");}
- 语法:
- 核心DOM:只能判断有没有
操作样式
-
内联:优先级最高,只会操作某个元素,不会牵一发动全身
- 获取: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";
创建元素&渲染页面&删除元素
创建元素&渲染页面
创建元素:3步
-
var 空标签=document.createElement("标签名"); -
设置必要的属性或事件
空标签.属性名="值"空标签.on事件名=function(){//操作}
-
渲染页面元素:3种
父元素.appendChild(新元素);//新元素会插入到父元素里面的末尾父元素.insertBefore(新元素,已有子元素);//新元素会插入到父元素里面的已有子元素之前 - 不推荐:修改其他的人下标父元素.replaceChild(新元素,已有子元素);//新元素会替换掉父元素里面的已有子元素
-
删除元素:
元素.remove();
HTML DOM常用对象
HTML DOM提供了一些常用对象:简化了核心DOM的操作,但是不是所有都能简化
-
image:简化了创建
- 语法:
var img=new Image(); - 强调:在DOM中,不是所有元素都具有构造函数创建方式
- 语法:
-
form:简化了查找
- 查找form元素:
var form=document.forms[i]; - 查找表单控件:
var input=form.elements[i]; - 专属事件:
onsubmit事件:提交的一瞬间会执行,也可以阻止提交return false;
- 查找form元素:
-
select:
-
属性:2个
- options === children:获取到select下面的所有的option
- selectedIndex - 获取到当前选中项的下标,只要是做联动,必不可少
-
方法:
select.add(option);,完全等效于appendChild,追加元素select.remove(i);,删除select中的第i个option- 专属事件:
onchange:选中项发生改变时触发
-
-
option:简化了创建
- 语法:
var opt=new Option("innerHTML","value");
- 语法:
BOM
BOM:Browser Object Model(浏览器 对象 模型),提供了专门用于操作浏览器的API(没有标准,使用的较少,但大部分浏览器厂商已经统一实现了(除了老IE))
BOM对象
BOM对象:window(定时器)、history、location、navigator、event、screen...
window对象
window对象:扮演了2个角色:
-
浏览器中,window代替了ES的Global充当全局作用域,包含了所有的全局对象、变量、函数
-
指代当前浏览器的窗口
网页打开新链接的方式(提升用户的体验感):
-
替换当前页面,可以后退:
HTML:
<a href="url">文字</a>JS:
open("url","_self"); -
替换当前页面,禁止后退:
使用场景:电商网页:结账完毕后,不允许用户后退
history对象:保存了当前窗口的历史记录,功能:前进后退
location:保存了当前窗口正在打开的url
语法:
location.replace("新url");,替换当前网址、不会产生历史记录 -
在新窗口打开,可以打开多个:
HTML:
<a href="url" target="_blank">文字</a>JS:
open("url","_blank"); -
在新窗口打开,只能打开一个:
使用场景:电商网页:跳转到 支付结账页面,只允许用户打开一个
HTML:
<a href="url" target="自定义">文字</a>JS:
open("url","自定义");自定义:窗口的底层都有一个名字,如果出现重复的名字则新窗口会替换掉原来的旧窗口
扩展:a标签可以做的事?
- 跳转
- 锚点
- 下载:
<a href="xx.rar/zip/exe">文字</a> - 打开图片、txt:
<a href="xx.图片后缀/txt">文字</a> - 直接书写js:
<a href="javascript:js代码;">文字</a>
window对象的属性和方法:
-
属性:
- 获取浏览器窗口的大小:
-
文档显示区域的大小:body部分
innerWidth/innerHeight -
完整的浏览器大小:
outerWidth/outerHeight -
屏幕的大小:桌面应用才用的
screen.width/height
-
- 获取浏览器窗口的大小:
-
方法:
-
打开新窗口:
-
语法:
var newW=open("url","自定义name","width=,height=,left=,top="); -
特殊:
-
如果没传入第三个参数,新窗口会和浏览器并为一体
-
如果传入第三个参数,新窗口会脱离浏览器
-
建议宽高不小于200
-
有可能会被浏览器拦截
-
-
-
关闭窗口:
- 语法:
窗口.close();
- 语法:
-
修改窗口的大小:
- 语法:
新窗口.resizeTo(newW,newH);
- 语法:
-
修改窗口的位置:
- 语法:
新窗口.moveTo(x,y);
- 语法:
-
定时器:2种
-
周期性定时器:先等待,在执行一次,在等待,在执行一次...
- 开启:
timer=setInterval(callback,间隔毫秒数); - 停止:
clearInterval(timer);
- 开启:
-
一次性定时器:先等待,在执行一次,结束
- 开启:
timer=setTimeout(callback,间隔毫秒数); - 停止:
clearTimeout(timer);
- 开启:
-
注意:两种定时器底层相同,可以互换
-
扩展:获取鼠标的坐标:
- 事件中传入一个形参e->获得到事件对象event(其中一个作用获取鼠标的坐标)
- 获取:
e.screenX/Y;//相对于屏幕
e.clientX/Y;//相对于浏览器客户端
e.pageX/Y;//相对于网页的
举例:
鼠标跟随效果:关键点:
1、绑定事件:window.onmousemove
2、图片位置一定和鼠标位置一起
3、图片的加载速度比js的执行速度要慢,
img.onload=function(){
//最后才会执行
}
history
history:保存当前窗口的历史记录(历史url) 作用:
- 前进:history.go(1);
- 后退:history.go(-1);
- 刷新:history.go(0);
location
location:保存当前窗口的正在打开的url
- 常识:一个url由5部分组成
举例:
http://127.0.0.1:8020/bom02/new/01-3.html
https://www.baidu.com/s?wd=178&rsv_spt=1&rsv_iqid=0xd702eab1000426fa&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&rqlang=cn&tn=baiduhome_pg&rsv_enter=1&rsv_dl=tb&oq=178%2526lt%253B&rsv_btype=t&inputT=204&rsv_t=8b56iJOG%2B6b45FILzCXex%2FpEHFfVJ6HMrt%2FXQdYMKdOy%2B8bu9OZqejCb14LrHOIywVaU&rsv_sug3=7&rsv_sug1=4&rsv_sug7=100&rsv_pq=a3ee42be00024fae&rsv_sug2=0&rsv_sug4=981
1. 协议:http/https(请求响应模式)/ftp(传输文件)/ws(广播收听模式:直播) - 网页的功能不同
2. 主机号/域名:www.baidu.com/127.0.0.1 - 主机号不方便记忆所以多半都会购买域名,而且127.0.0.1只能访问自己
3. 端口号::8020 - 默认端口:http - 80 https - 443,默认端口可以省略不写
4. 文件的相对路径:new/01-3.html /s -百度加密了
5. 查询字符串:?wd=178&rsv_spt=1... - 表单提交到服务器的东西 - 请求消息
-
属性:不需要记忆,直接用console.log(location)可以查看到有哪些属性
- 作用:获取:协议、域名、端口号、文件路径、查询字符串
-
API:跳转
location="新url"location.href="新url"location.assign("新url");- 替换后禁止后退:
location.replace("新url") - 刷新:
location.reload();
navigator
navigator:保存了当前浏览器的信息(浏览器的名称/版本号)
- 属性:
navigator.userAgent; - 作用:根据字符串截取出浏览器名称&版本号:本来的目的是为了做兼容,但是没用因为所有的API前辈们都已经设置好了兼容
event
event:事件对象
- 事件:多半用户触发或浏览器自动触发的操作
-
绑定事件:3种
-
在HTML元素上绑定
- 语法:
<elem on事件名="js语句"></elem> - 缺点:
- 没有实现JS与HTML的分离 - 要HTML(内容)/CSS(样式)/JS(行为)分离
- 无法动态绑定事件 - 一次只能绑定一个元素
- 无法同时绑定多个函数对象
- 语法:
-
使用JS的事件属性绑定:
- 语法:
elem.on事件名=function(){js语句} - 优点:
- 实现JS与HTML的分离
- 动态绑定事件
- 缺点:无法同时绑定多个函数对象
- 语法:
-
使用JS的API绑定事件:
-
主流:
elem.addEventListener("事件名",callback) -
老IE:
elem.attachEvent("on事件名",callback); -
兼容:
if(elem.addEventListener){ elem.addEventListener("事件名",callback) }else{ elem.attachEvent("on事件名",callback); } -
优点:
- 实现JS与HTML的分离
- 动态绑定事件
- 同时绑定多个函数对象
-
缺点:需要处理兼容性问题
-
-
-
事件周期:
- 主流:3个
- 捕获阶段:由外向内,记录着要执行的事件
- 目标触发:当前点击的元素优先出发
- 冒泡触发:由内向外的冒泡触发事件
- 老IE:2个
- 目标触发:当前点击的元素优先出发
- 冒泡触发:由内向外的冒泡触发事件
- 主流:3个
-
获取到事件对象event:
-
主流:事件函数中传入一个形参e,就可以自动接住事件对象
event -
老IE:
window.event; -
兼容:
event;,不光老IE可用,主流浏览器也可以使用 -
获取到了事件对象event就可以做操作了:
-
获取鼠标的位置
-
阻止冒泡:重要在于面试中/鄙视中,但是开发中绝对不会阻止冒泡,更需要利用冒泡
- 主流:
e.stopPropagation(); - 老IE:
e.cancelBubble=true; - 兼容:
if(e.stopPropagation){e.stopPropagation()}else{e.cancelBubble=true;}
- 主流:
-
事件委托(利用冒泡):
-
为什么:优化,每绑定一个事件,相当于就创建了一个事件监听对象,创建的对象越多,网页的性能越底下
-
建议:建议把事件都绑定在自己的父元素身上一次即可
-
获取目标元素:
触发的元素 - > 永远不变就是你触发到的元素
当前元素:this -> 指向很多
语法: 主流:e.target; 老IE:e.srcElement; 兼容:e.srcElement;不光老IE可用,主流浏览器也可以使用
-
-
阻止浏览器的默认行为:
-
默认行为:比如:F5带来的刷新,F12带来的控制台,右键带来的菜单框,F11全屏,a自带跳转,submit自带提交...
语法: 主流:e.preventDefault(); 老IE:e.returnValue=false; 兼容:if(e.preventDefault){ e.preventDefault() }else{ e.returnValue=false; } -
新事件:
鼠标右击:window.oncontextmenu
键盘事件:window.onkeydown
-
-
获取键盘的键码
语法:
e.keyCode;
-
-
扩展:客户端存储技术 - 以前使用cookie(缺点:大小有限2kb,30天必死),HTML5提出了一个新概念webStorage:2种(优:大小有限8mb,生命周期无限,缺点:老IE不支持) 1. localStorage:本地级 - 浏览器关闭甚至电脑关闭,第二天打开依然存在 2. sessionStorage:会话级 - 浏览器一旦关闭自动死亡
-
作用:
- 数据可以跨页面传输
- 皮肤、主题
- 浏览器的历史记录
-
语法:非常简单,类似于对象:
- 添加:
xxxxStorage.属性名="值"; - 获取:
xxxxStorage.属性名; - 删除:
xxxxStorage.removeItem("属性名");,只会删除这一个 - 清空:
xxxxStorage.clear();,删除所有
- 添加: