现代的 JavaScript 是一种“安全的”编程语言。它不提供对内存或 CPU 的底层访问,因为它最初是为浏览器创建的,不需要这些功能。
JavaScript 的能力很大程度上取决于它运行的环境。例如,Node.js 支持允许 JavaScript 读取/写入任意文件,执行网络请求等的函数。
浏览器中的 JavaScript 可以做与网页操作、用户交互和 Web 服务器相关的所有事情。
例如,浏览器中的 JavaScript 可以做下面这些事:
为了用户的(信息)安全,在浏览器中的 JavaScript 的能力是受限的。目的是防止恶意网页获取用户私人信息或损害用户数据。
此类限制的例子包括:
网页中的 JavaScript 不能读、写、复制和执行硬盘上的任意文件。它没有直接访问操作系统的功能。
现代浏览器允许 JavaScript 做一些文件相关的操作,但是这个操作是受到限制的。仅当用户做出特定的行为,JavaScript才能操作这个文件。例如,用户把文件“拖放”到浏览器中,或者通过 标签选择了文件。
有很多与相机/麦克风和其它设备进行交互的方式,但是这些都需要获得用户的明确许可。因此,启用了 JavaScript的网页应该不会偷偷地启动网络摄像头观察你,并把你的信息发送到 美国国家安全局。
不同的标签页/窗口之间通常互不了解。有时候,也会有一些联系,例如一个标签页通过 JavaScript打开的另外一个标签页。但即使在这种情况下,如果两个标签页打开的不是同一个网站(域名、协议或者端口任一不相同的网站),它们都不能相互通信。
这就是所谓的“同源策略”。为了解决“同源策略”问题,两个标签页必须都包含一些处理这个问题的特定的 JavaScript代码,并均允许数据交换。
这个限制也是为了用户的信息安全。例如,用户打开的 http://anysite.com 网页必须不能访问http://gmail.com(另外一个标签页打开的网页)也不能从那里窃取信息。
JavaScript可以轻松地通过互联网与当前页面所在的服务器进行通信。但是从其他网站/域的服务器中接收数据的能力被削弱了。尽管可以,但是需要来自远程服务器的明确协议(在HTTP header 中)。这也是为了用户的信息安全。
如果在浏览器环境外(例如在服务器上)使用 JavaScript,则不存在此类限制。现代浏览器还允许安装可能会要求扩展权限的插件/扩展。
三大对象
在JavaScript中提供三种自带的对象,分别是"本地对象" “内置对象” “宿主对象”
JS中常用的内置对象:Array对象、Date对象、正则表达式对象、string对象、Global对象等。
因为文档页面从上往下加载,所以先有标签,然后才能getElementById
参数是字符串,所以需要加引号
返回的是一个 element 对象
console.dir 可以打印返回的元素对象,更好的查看里面的属性和方法
支持HTML5的各主流浏览器的最低版本:
onclick:点击某个对象时触发
ondblclick:双击某个对象时触发
onmouseover:鼠标移入某个元素时触发
onmouseout:鼠标移出某个元素时触发
onmouseenter:鼠标进入某个元素时触发
onmouseleave:鼠标离开某个元素时触发
onmousedown:鼠标按下时触发
onmouseup:鼠标抬起时触发
onmousemove:鼠标被移动时触发
onwheel:鼠标滚轮滚动时触发
oncontextmenu:点击鼠标右键时触发
onkeydown:键盘的键按下时触发
onkeyup:键盘的键放开时触发
onkeypress:按下或按住键盘键时触发
onresize:浏览器窗口大小改变时触发
onabort:图形的加载被中断时触发
onload:元素加载完时触发
onerror:当加载文档或者图片时(没找到)发生的错误时触发
onscroll:文档滚动时触发
onpageshow:用户访问页面时触发
onunload:用户退出页面时触发
onfocus:元素获得焦点时触发
onblur:元素失去焦点时触发
onchange:元素内容改变时触发
oninput:元素获取用户输入时触发
onsubmit:提交按钮时触发
onreset:重置按钮时触发
onselect:文本被选中时触发
ondrag:元素正在拖动时触发
ondragend:用户完成元素拖动时触发
onplay:在视频/音频开始播放时触发
onended:在视频/音频播放结束时触发
onpause:在视频/音频暂停时触发
给元素添加事件,称为注册事件或者绑定事件。
注册事件有两种方式:传统方式和方法监听注册方式
利用on开头的事件onclick
btn.onclick = function () {}
特点:注册事件的唯一性
同一个元素同一个事件著能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
W3C标准推荐方式
addEventListener() 它是一个方法
IE9之前的IE浏览器不支持此方法,可使用attachEvent()代替
特点: 同一个元素同一个事件可以注册多个监听器
addEventListener() 方法
eventTarget.addEventListener(type, listener, [useCapture])
eventTarget.addEventListener(type, listener, [useCapture]) 方法将指定的监听器注册到eventTarget 上,当该对象触发指定的事件时,就会执行事件处理函数。
该方法接收三个参数:
attachEvent
该特性非标准,请尽量不要在生产环境中使用它
eventTarget.attackEvent(eventNameWithon, callback)
eventTarget.attackEvent方法将指定的监听器注册到eventTarget 上,当该对象触发指定的事件时,指定的回调函数将会被执行。
该方法接收两个参数:
<button>点击我</button>
<script>
var btn = document.querySelector('button');
function alertWarn () {
alert ('warning');
}
function addEventListener(element, eventName, fn) {
//判断浏览器是否支持addEventListener方法
if (element.addEventListener) {
element.addEventListener (eventName, fn); //第三个参数,默认是false
} else if (element.attachEvent) {
element.attachEvent ('on' + eventName, fn);
} else {
//相当于element.onclick = fn;
element['on' + eventName] = fn;
}
}
addEventListener(btn, 'click', alertWarn);
</script>
eventTarget.onclick = null;
divs[1].addEventListener('click', alertWarn);
function alertWarn () {
alert('warning');
divs[1].removeEventListener('click', alertWarn);
}
divs[2].attachEvent('onclick', alertWarn1);
function alertWarn1 () {
alert('warning');
divs[1].detachEvent('click', alertWarn1);
}
参考上面的注册事件的兼容性方式。
事件流描述的是从页面中接收事件的顺序。
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。
包括三个阶段:
注意:
兼容性写法:
event = event || windoe.event;
事件对象属性方法 | 说明 |
---|---|
e.target | 返回触发事件的对象 标准 |
e.scrElement | 返回触发事件的对象 非标准 IE 6 7 8 使用 |
e.type | 返回触发事件的对象 非标准 IE 6 7 8 使用 |
e.cancelBubble | 该属性阻止冒泡,非标准,IE 6 7 8 使用 |
e.returnValue | 该属性阻止默认事件(默认行为)非标准 ,IE 6 7 8 使用,比如不让链接跳转 |
e.preventDefaule() | 该方法阻止默认事件(默认行为)标准 ,比如不让链接跳转 |
e.stopPropagation() | 阻止冒泡,标准 |
e.target 和 this 的区别
var ul = document.querySelector('ul');
ul.addEventListener('click', function (e) {
console.log(this);
console.log(e.target);
})
// ...
// 123
三种方法:
var father = document.querySelector('.father');
var son = document.querySelector('.son');
father.addEventListener('click', alertName, false);
son.addEventListener('click', alertName, false);
document.addEventListener('click',function () {
alert('document');
}, false);
function alertName (event) {
alert(this.getAttribute("class"));
event.stopPropagation(); // 停止冒泡
event.cancelBubble; // IE 6 7 8 的停止冒泡
}
事件委托的原理
不给每个子节点单独设置事件监听器,而是设置在其父节点上,然后利用冒泡原理设置每个子节点。
例如:给 ul 注册点击事件,然后利用事件对象的 target 来找到当前点击的 li ,然后事件冒泡到 ul 上, ul 有注册事件,就会触发事件监听器。
事件委托的作用
只操作了一次 DOM ,提高了程序的性能。
// Element对象是所有标签元素的基础对象,封装了所有标签元素的公共方法与属性
// 常用属性
Element.attributes // 获得所有属性key-value集合
Element.className // 获得类名(可读写)=>idea:elem.className = 'pink',然后再css定义
// 注意:此方法会覆盖原有类名
Element.classList // 返回一个元素的类属性的实时 DOMTokenList 集合(只读),通过其内部方法修改
// ie10+,
Element.id // 获取元素id
Element.innerHTML // 获取元素内部包裹的html标签字符串(可读写)
Element.innerText // 获取元素内部文本,标签不识别会直接进行显示(可读写)
Element.tagName // (只读)获取元素的标签名字符串
Element.style // 获取/修改style样式,如Element.style.backgroundColor
// 常用方法
Element.getAttribute(attrName) // 返回属性的字符串值,适合获取自定义属性data-
Element.removeAttribute(attrName) // 从指定的元素中删除一个属性
Element.setAttribute(attrName,value) // 设置属性
Element.hasAttribute(attrName) // 检测属性是否存在
Element.getElementsByClassName() // 获取后代元素根据className
Element.getElementsByTagName() // 获取后代元素根据tagName
...
Element.dataset.index | Element.dataset['index'] // 用于获取data-自定义属性(h5新增),支持驼峰命名获取(ie11+)
// HTMLCollection对象,是伪数组。元素的动态集合,提供了用来从该集合选择元素的方法和属性,当其所包含的文档结构发生改变时,会自动更新.
// 常用属性
HTMLCollection.length // 返回集合中子元素的数组
// 常用方法
HTMLCollection.item() // 根据给定的索引(从0开始),返回具体的节点
HTMLCollection.namedItem() // 根据 Id 返回指定节点,或者作为备用,根据字符串所表示的 name 属性来匹配
获取属性值
element.属性 获取内置属性值(元素自带的属性)
element.getAttribute(‘属性’) 主要获取自定义的属性(标准),我们定义的属性
设置属性值
element.属性 = ‘值’;
element.setAttribute(‘属性’, ‘值’) 主要更改自定义的属性
移除属性值
element.removeAttribute(‘属性’) 主要移除自定义的属性(标准)
document.innerHTML()
将内容写入某个DOM节点,不会导致页面全部重绘
拼接字符串的效率低
创建多个元素效率更高,(不要拼接字符串,采取数组形式拼接),结构稍显复杂
document.createElement()
创建多个元素效率稍低一点点,但是结构更清晰
总结:不同浏览器下,innerHTML比createElement效率高
两层循环,先排除其他人,然后再设置自己的样式
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
var btns = document.querySelectorAll('button');
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function () {
// 1. 先把所有颜色的背景颜色都清空
for (var j = 0; j < btns.length; j++) {
btns[j].style.backgroundColor = '';
}
// 2. 再把想要的背景颜色改成pink
this.style.backgroundColor = 'pink';
}
}
</script>
自定义属性目的:为了保存并使用数据,有些数据保存到页面中,为不是数据库中
设置H5自定义属性
但是有些自定义属性容易引以歧义,不容易判断是内置属性还是自定义属性,所以H5给我们新增了自定义属性 H5规定自定义属性以 “data-” 开头
获取H5自定义属性
兼容性:element.getAttribute(‘属性’)
H5新增:element.dataset.index 或者 element.dataset[ ‘index’ ]
注意:
<div data-list-name="andy"></div>
<script>
var div = document.querySelector('div');
console.log(div.getAttribute('data-list-name'));
//上下三种方法都可以,但是如果用下面这两种方法的话,要用驼峰命名法
console.log(div.dataset.listName);
console.log(div.dataset['listName']);
</script>
利用DOM提供的方法获取元素 (逻辑性不强,繁琐)
document.getElementById()
document.getElementByTagName()
document.querySelector 等等
利用 (简单、符合逻辑)
利用父子兄的节点关系获取元素
逻辑性强,但是兼容性差
页面中所有的内容(标签、属性、文本、注释等)都是节点。节点用node表示。
HTML DOM树中的所有节点均可通过JavaScript 进行访问,所有HTML节点均可被修改,也可以创建或删除。
一般的,节点至少由nodeType(节点类型)、 nodeName(节点名称)、 nodeValue(节点值)这三个基本属性。
元素节点 nodeType 为1
属性节点 nodeType 为2
文本节点 nodeType 为3 (文本节点包括文字、空格、换行等等)
在实际开发中,节点操作主要操作的是元素节点。
最常见的是父子兄层级关系。
node.parentNode
注意:得到的离元素最近的父级节点(亲爸爸),如果找不到就返回null
返回包含指定节点的子节点的集合,该集合为即时更新的集合 包含的子节点包含元素节点、文本节点等等
用 nodeType 判断,用for循环遍历
得到所有的子元素节点,虽然是非标准的,但是得到了浏览器的支持,所以以后大量使用这个
返回第一个子节点,找不到返回null,不管是文本节点还是元素节点都能找到
返回第一个子元素节点,找不到返回null,只返回元素节点(IE9以上才支持)
返回最后一个子节点,找不到返回null,不管是文本节点还是元素节点都能找到
返回最后一个子元素节点,找不到返回null,只返回元素节点(IE9以上才支持)
实际开发中的办法:
parentNode.children[i]
//下面两个方法只有IE9以上才能兼容
这个方法创建由tagName指定的 HTML 元素,因为这些元素原先不存在,是根据我们的需求动态生成的,所以也称为动态创建元素节点。
它是追加元素,是在指定父节点的子节点的末尾添加。
node.removeChild(child);
从DOM中删除一个子节点,返回删除的节点
node.cloneNode() 这个方法返回一个节点的副本
注意:
如果括号里面的参数为空,那么只是浅拷贝,即只复制节点本身,不克隆里面的子节点
如果括号里面的参数为true,那么是深拷贝,复制标签并且复制里面的内容
BOM(Brower Object Model) 即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window。
BOM 是由一系列相关的对象构成,并且每个对象都提供了很多方法和属性。
BOM 缺乏标准,JavaScript 语法的标准化组织是 ECMA,DOM 的标准化组织是 W3C,BOM 最初是 Netscape 浏览器标准的一部分。每个浏览器都有自己的标准。
window 对象是浏览器的顶级对象,它具有双重角色。
它是 JS 访问浏览器窗口的一个接口。
它是一个全局对象,定义在全局作用域中的变量、函数都会变成 window 对象的属性和方法。
在调用的时候可以省略 window,前面学习的对话框都属于 window 对象方法,如 alert()、prompt() 等。
window.onload = function() {}
或者
window.addEventListener("load",function(){});
window.onload 是窗口(页面)加载事件,当文档内容完全加载完成后会触发该事件(包括图像、脚本文件、CSS文件等)。
window.onload 只能写一次,当写了很多个的时候,只有最后一个起作用, 所以推荐第二种写法。
window.addEventListener("DOMContentLoaded",function(){});
这个事件当 DOM 加载完成时触发,不包含 CSS、图片、flash 等。
IE9+ 支持。
window.onresize = function() {}
或者
window.addEventListener("resize",function(){});
这是调整窗口大小的时候的触发事件。包括窗口高度和宽度。
经常用来实现响应式布局。 window.inner.width 当前屏幕的宽度
window 对象提供了2个好用的方法——定时器:
setTimeout()
setInterval()
window.setTimeout(调用函数, [延迟的毫秒数]);
setTimeout() 方法用于设置一个定时器,该定时器在定时器到期后执行调用函数。
这个 window 在调用的时候可以省略。
这个延时时间单位是毫秒,可以省略,如果省略默认是0。
这个调用函数可以直接写函数,还可以写函数名,函数名后面不写括号。
页面中可能有很多的定时器,我们经常给定时器加标识符(名字)。
window.clearTimeout(timeoutID)
window 可以省略
里面的参数是定时器的标识符
window.setInterval(调用函数, [延迟的毫秒数]);
setInterval() 方法重复调用一个函数,每隔这个时间,就去调用一次回调函数
window.clearInterval(intervalID);
window 可以省略
里面的参数是定时器的标识符
JS 的一大特点就是单线程,也就是说,同一时间只能做一件事,这是因为 JS这门语言诞生的使命导致的—— JS 是为处理页面中用户的交互,以及操作 DOM 而诞生的。比如我们对某个 DOM 元素进行添加和删除操作,不能同时进行。应该先添加,然后再删除。
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是:如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程。于是,JS 中出现了 同步 和 异步 。
同步任务:同步任务都在主线程上执行,形成一个执行栈。
异步任务: JS 的异步是通过回调函数实现的。
一般而言,异步任务有以下三种类型:
异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)。
由于主现程不断地重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环(evwnt loop)。
window 对象给我们提供了一个 location 属性用于获取或设置窗体的URL,并且可以用于解析URL。因为这个属性返回的是一个对象,所以我们将这个属性也称为 location 对象。
URL
统一资源定位符(Uniform Resource Locator,URL)是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
URL 的一般语法结构为:
porotocol://host[:port]/path/[?query]#fragment
http://www.itcast.cn/index.html?name=andy&age=18#link
组成 | 说明 |
---|---|
protocol | 通信协议,常用的http、ftp、maito等 |
host | 主机(域名) |
port | 端口号,可选,省略时使用默认断开,如http的默认端口80 |
path | 路径,由零或多个“/”格开的字符串,一般用来表示主机上的一个目录或者文件地址 |
query | 参数,以键值对的形式,通过符号 & 分割开来 |
fragment | 片段 ,# 后面的内容常见于链接,锚点 |
location 对象属性 | 返回值 |
---|---|
location.href | 获取或者设置整个 URL |
location.host | 返回主机(域名 |
location.port | 返回端口号,如果未写返回空字符串 |
location.pathname | 返回路径 |
location.search | 返回参数 |
location.hash | 返回片段,# 后面内容,常见于链接、锚点 |
location 对象方法 | 返回值 |
---|---|
location.assign() | 跟 href 一样,可以跳转页面 |
location.replace() | 替换当前页面,因为不记录历史,所以不能后退页面 |
location.replace() | 重新加载页面,相当于刷新按钮或者 F5,如果参数为true,强制刷新ctrl + F5 |
navigator对象包含有关浏览器的信息,它有很多属性,我们最常用的是userAgent,该属性可以返回由客户机发送服务器的useragent头部的值。
window对象给我们提供了一个history对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL。
history 对象方法 | 作用 |
---|---|
back() | 后退功能 |
forward() | 前进功能 |
go(参数) | 前进后退功能,参数如果是1,前进一个页面,如果是-1,后退一个页面 |
history 对象在一般的实际开发中比较少用,但是会在一些 OA 办公系统中见到。
offset 翻译过来就是偏移量,我们使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等。
获得元素距离带有定位父元素的位置
可以获取元素自身的宽度和高度
注意:返回的数值不带单位
offset 系列常用属性:
offset 系列属性 | 作用 |
---|---|
element.offsetParent | 返回作为该元素带有定位的父级元素如果父级都没有定位则返回body |
element.offsetTop | 返回元素相对带有定位父元素上方的偏移 |
element.offsetLeft | 返回元素相对带有定位父元素左边框的偏移 |
element.offsetWidth | 返回自身包括padding、边框、内容区的宽度,返回数值不带单位 |
element.offsetHeight | 返回自身包括padding、边框、内容区的高度,返回数值不带单位 |
offset 和 style 区别:
offset | style |
---|---|
offset 可以得到任意样式表中的样式值 | style 只能得到行内样式表中的样式值 |
offset 系列获得的数值没有单位 | style.width 获得的是带有单位的字符串 |
offsetWidth 包含 padding + border + width | style.width 获得不包括padding + border的值 |
offsetWidth 等属性是只读属性,只能获取不能修改 | style.width 是可读写属性,可以获取也可以赋值 |
我们想要获取元素的大小位置,用 offset 更合适 | 想要给元素更改值,用style 改变 |
client 翻译过来就是客户端,我们使用 client 系列的相关属性来获取元素可是去的相关信息。通过 client 系列的相关属性可以动态的得到该元素的边框大小、元素大小等。
client 系列属性 | 作用 |
---|---|
element.clientTop | 返回元素上边框的大小 |
element.clientLeft | 返回元素左边框的大小 |
element.clientWidth | 返回自身包括padding、内容区的宽度,不含边框,返回数值不带单位 |
element.clientHeight | 返回自身包括padding、内容区的高度,不含边框,返回数值不带单位 |
不需要调用,立马能够自己执行的函数。 立即执行函数的作用就是独立创建了一个作用域,可以避免函数内的变量暴露在全局环境下,避免全局变量的污染,里面所有的变量都是局部变量,避免了命名冲突的问题。
写法
(function() {})() 或者 (function(){}())。
通过scroll可以动态获取该元素的大小,滚动距离等
注意:
返回值是不带单位的
页面的滚动距离通过window.pageXOffset获取
scroll | 作用 |
---|---|
element.scrollTop | 返回被卷去的上侧距离 |
element.scrollLeft | 返回被卷去的左侧距离 |
element.scrollWidth | 返回自身实际的宽度(包括超出盒子的内容),不含边框,包含padding |
element.scrollHeight | 返回自身实际的高度(包括超出盒子的内容),不含边框,包含padding |
核心原理: 通过定时器setInterval()不断移动盒子距离
function animate(obj, target, callback) {
clearInterval(obj.timer)
obj.timer = setInterval(function() {
// 步长值写到定时器里面
// 把我们步长值改为整数 不要出现小数的问题
var step = Math.ceil((target - obj.offsetLeft) / 10);
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画,本质上是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
//if (callback) {
// 调用函数
// callback();
//}
callback && callback();
}
// 把每次加1这个步长值改为一个慢慢变小的值。步长公式:(目标值-现在的位置)/10
obj.style.left = obj.offsetLeft + step + 'px';
}, 15)
}
引入:
使用:
<script>
var sliderbar = document.querySelector('.sliderbar');
var con = document.querySelector('.con');
sliderbar.addEventListener('mouseenter', function() {
animate(con, -160, function() {
sliderbar.children[0].innerHTML = '->';
})
});
sliderbar.addEventListener('mouseleave', function() {
animate(con, -160, function() {
sliderbar.children[0].innerHTML = '<-';
})
});
</script>
克隆第一张图片,然后图片滚动克隆的图片后迅速跳过第一张图片,因为js执行速度很快,所以用户看上去就像滚动的第一张,实际滚动的是克隆的图片
swiper插件开发移动端轮播图
superslide
iscroll
生命周期为关闭浏览器窗口
在同一窗口(页面)下数据可以共享
以键值对的形式存储使用
const user = { name: '隔壁老王', age: 18 }
// sessionStorage
// 存储数据
sessionStorage.setItem('user', JSON.stringify(user, null, 2))
// 修改数据 => 重新存储即可
// 读取数据
sessionStorage.getItem('user')
// 删除数据
sessionStorage.removeItem('user')
// 清空数据
sessionStorage.clear()
生命周期永久生效,除非手动删除否则关闭页面也会存在
可以多窗口(页面)共享(同一浏览器可以共享数据)
以键值对的形式存储使用
const user = { name: '隔壁老王', age: 18 }
// localStorage
// 存储数据
localStorage.setItem('user', JSON.stringify(user, null, 2))
// 修改数据 => 重新存储即可
// 读取数据
localStorage.getItem('user')
// 删除数据
localStorage.removeItem('user')
// 清空数据
localStorage.clear()