JS高级语法与JS选择器

时间:2023-03-09 14:34:28
JS高级语法与JS选择器

元素(element)和节点(node)

childNode属性和children属性的区别

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="parentDiv">
<!--注释-->
<div></div>
</div>
<script>
console.log(document.getElementById('parentDiv').childNodes); //NodeList[5]
console.log(document.getElementById('parentDiv').children) ; //HTMLCollection[1]
</script>
</body>
</html>

JS高级语法与JS选择器

childNodes属性返回的是NodeList数组,是属于节点(也包括元素)的属性,而children属性返回的是子元素,是属于元素的属性

而在Nodelist数组里面也有元素存在,证明了元素也是节点的一种,即元素节点。

W3C中的解释是:

在 HTML DOM (文档对象模型)中,每个部分都是节点

文档本身是文档节点
所有 HTML 元素是元素节点
所有 HTML 属性是属性节点
HTML 元素内的文本是文本节点 (包括回车符,空格,空白字符也是属于文本节点)
注释是注释节点

Element 对象可以拥有类型为元素节点、文本节点、注释节点的子节点。

NodeList 对象表示节点列表,比如 HTML 元素的子节点集合。

元素也可以拥有属性。属性是属性节点。
总结:元素是元素节点,是节点中的一种,但元素节点中可以包含很多的节点

nodeName(纯大写) 属性含有某个节点的名称

元素节点的nodeName 是标签名称
属性节点的nodeName 是属性名称
文本节点的nodeName 永远是 #text
文档节点的nodeName 永远是 #document

nodeValue
对于文本节点,nodeValue 属性包含文本。
对于属性节点,nodeValue 属性包含属性值
nodeValue 属性对于文档节点和元素节点是不可用的 

nodeType 属性可返回节点的类型

Element 元素     1
Attribute 属性 2
Text 文本 3
CDATA Section CDATA断 4
Entity Reference 实体参数 5
Entity 实体    6
Processing Instrucion 处理指令 7
Comment 注释 8
Document 文档 9
Document Type 文档类型 10
Document Fragment 文档片断 11

添加和删除节点(HTML 元素)

创建新的 HTML 元素

如需向 HTML DOM 添加新元素,您必须首先创建该元素(元素节点),然后向一个已存在的元素追加该元素

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="div1">
<p id="p1">这是一个段落</p>
<p id="p2">这是另一个段落</p>
</div> </body>
<script>
var para=document.createElement("p"); var node=document.createTextNode("这是新段落。");
para.appendChild(node); var element=document.getElementById("div1");
element.appendChild(para);
</script>
</html> <!-- 为这段代码创建新的 <p> 元素:
var para=document.createElement("p");
此时检查页面可以看到div里面已经生成了<p>元素 如需向 <p> 元素添加文本,您必须首先创建文本节点。
这段代码创建了一个文本节点:
var node=document.createTextNode("这是新段落。");
然后您必须向 <p> 元素追加这个文本节点:
para.appendChild(node);
最后您必须向一个已有的元素追加这个新元素。
这段代码找到一个已有的元素:
var element=document.getElementById("div1");
这段代码向这个已有的元素追加新元素:
element.appendChild(para); -->

JS高级语法与JS选择器

删除已有的 HTML 元素

如需删除 HTML 元素,您必须首先获得该元素的父元素

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <div id="div1">
<p id="p1">这是一个段落。</p>
<p id="p2">这是另一个段落。</p>
</div> </body>
<script>
var parent=document.getElementById("div1"); var child=document.getElementById("p1"); parent.removeChild(child);
</script>
</html> <!-- 例子解释:
这个 HTML 文档含有拥有两个子节点(两个 <p> 元素)的 <div> 元素:
<div id="div1">
<p id="p1">这是一个段落。</p>
<p id="p2">这是另一个段落。</p>
</div> 找到 id="div1" 的元素:
var parent=document.getElementById("div1");
找到 id="p1" 的 <p> 元素:
var child=document.getElementById("p1"); 从父元素中删除子元素:
parent.removeChild(child); 提示:如果能够在不引用父元素的情况下删除某个元素,就太好了。
不过很遗憾。DOM 需要清楚您需要删除的元素,以及它的父元素。
这是常用的解决方案:
找到您希望删除的子元素,然后使用其 parentNode 属性来找到父元素:
var child=document.getElementById("p1");
child.parentNode.removeChild(child); -->

常用节点操作

1.节点查找
document.getElementById,document.getElementByTagName,document.getElementByName ,document.getElementByClassName
document.querySelector() 参数为选择器
document.forms 选取页面中的所有表单元素
2.增加节点
增加节点前必须先使用document.createElement()创建元素节点,参数为标签名
m.appendChild(n) 为m元素在末尾添加n节点
m.insertBefore(k,n) 在m元素的k节点前添加n节点
3.删除节点
m.removeChild(n)删除m元素中的n节点
m.replaceChild(k,n)用n节点取代m元素中的k节点
4.复制节点
m.cloneChild() 复制m节点,并将复制出来的节点作为返回值
参数为true时,则将m元素的后代元素也一并复制。否则,仅复制m元素本身 节点属性操作 节点(自身)属性: attributes - 节点(元素)的 属性节点
nodeType – 节点类型
nodeValue – 节点值
nodeName – 节点名称
innerHTML - 节点(元素)的文本值 1.节点属性值选取
m.属性名 (:驼峰形式 ) m.className
m[“属性名”] m.['className'] m.getAttribute(“属性名”) :加引号,html的形式 m.getAttribute("class") 2.节点属性修改
前两种选取方法时,直接赋值即可
m.setAttribute("属性名",“值”) 3.创建属性节点并设置属性值
var info_node=document.createAttribute(\"info\");//创建
info_node.value='123';//设置
sup1.setAttributeNode(info_node);//添加 4.复制节点
var body = document.querySelector('body');
true深拷贝,拷贝自身与内容, false浅拷贝,只拷贝自身标签
var cl_body = body.cloneNode(true);
console.log(cl_body); JS DOM节点(当前标签和同级、父级、子级..之间的关系)
1. 通过顶层document节点获取
1) document.getElementById(elementId) //根据id获得
2) document.getElementsByName(elementName) //根据name获得
3) document.getElementsByTagName(tagName) //根据标签名获得
2、通过父节点获取
1) parentObj.firstChild //获得第一个子节点
2) parentObj.lastChild //获得第二个子节点
3) parentObj.childNodes //获取作为指定对象直接后代的HTML元素和TextNode对象的集合
4) parentObj.children //非标准dom集合,建议使用childNodes
5) parentObj.getElementsByTagName(tagName) //获得该标签下标签名为tagName的所有标签
3、通过临近节点获取
1) neighbourNode.previousSibling //获得同级前一个标签
2) neighbourNode.nextSibling //获得同级后一个标签
4、通过子节点获取
1) childNode.parentNode //获得父标签

事件

onload:页面加载完毕事件,只附属于window对象
onclick:鼠标点击时间
onmouseover:鼠标悬浮事件
onmouseout:鼠标移开事件

on事件绑定方式

document.onclick = function() {
console.log("文档点击");
}

on事件只能绑定一个方法,重复绑定保留最后一次绑定的方法

document.onclick = function() {
console.log("文档点击");
}

事件的移除

document.onclick = null;

非on事件绑定方式

document.addEventListener('click', function() {
console.log("点击1");
})
document.addEventListener('click', function() {
console.log("点击2");
})

非on事件可以同时绑定多个方法,被绑定的方法依次被执行
addEventListener第三个参数(true|false)决定冒泡的方式

function fn () {}
document.addEventListener('click', fn);

事件的移除
document.removeEventListener('click', fn,false);

事件的三种绑定方式的思考

方法一:嵌入dom
把onclick绑定在标签上
HTML元素行间事件(也可以叫HTMl事件处理程序),直接在html标签里添加事件。
缺点:html和js代码紧密耦合
<input id="btn1" type="button" onclick="test();" /> 方法二:直接绑定
onclick的js绑定办法 //把一个函数赋值给一个事件处理程序属性。(这种方式也叫做Dom0级事件处理程序)
var btn1 = document.getElementById('btn1');
function abc() {
alert('abc');
}
btn1.onclick = abc; //当点击的时候执行abc这个函数,等价于 btn1.onclick=function abc(){alert('abc');}
//btn1.onclick = null; //去掉绑定的事件 方法三:事件监听 click的js绑定办法(js的话推荐这种)
//通过“事件监听”的方式来绑定事件(也叫Dom2级事件处理程序) var btn2 = document.getElementById('btn2');
btn2.addEventListener('click', showMsg, false); //鼠标单击的时候调用showMes这个函数
function showMsg() {
alert("事件监听");
}
//btn2.removeEventListener('click', showMsg, false); //去除绑定 方法一
最原始的写法:和html混合在一起写,缺点是代码高冗余,且无法添加多个事件处理函数如上文对事件的举例则为典型的**html事件处理程序*写法 方法二
dom0级:将html代码和js代码分离,且支持匿名函数,可以看到完美的改进了1的冗余缺憾,所有的事件相关操作都在js中完成 方法三
dom2级:ie使用attachEventListener其他非ie使用addEventListener,可以支持绑定多个事件,瞧吧,又一个缺憾被完美解决了~,而且dom2级还可以自定义事件流,下一篇会分析事件流模型 dom3级:对事件进行了更广而全的分类,请自行查阅

实例运用一

</head>
<body>
<div class="div"></div>
<div class="div"></div>
</body>
<script>
// js事件: 页面标签在满足某种条件下可以完成指定功能的这种过程, 成之为事件
// 某种条件: 如鼠标点击标签: 点击事件 | 鼠标双击标签: 双击事件 | 键盘按下: 键盘按下事件
// 指定功能: 就是开发者根据实际需求完整相应的功能实现 // 钩子函数: 就是满足某种条件被系统回调的函数(完成指定功能) // 点击事件: 明确激活钩子的条件 = 激活钩子后改处理什么逻辑, 完成指定功能(函数)
var div = document.querySelector(".div"); // 找到的是第一个.div
div.onclick = function () {
// alert(123)
this.style.backgroundColor = "pink";
} // 明确第一个及第二个
var divs = document.querySelectorAll('.div');
divs[1].ondblclick = function () {
divs[0].style.backgroundColor = "yellow";
} </script>
</html>

实例运用二

复习并延伸
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>复习预习</title>
<style>
[key='value'] {
color: #0f8209;
}
</style>
</head>
<body>
<div class="ele" alert="OK">div div div</div>
</body>
<script>
// 1.面向对象js
// ES5
// 普通的单一对象
var obj = {
// 普通对象的属性
key: "value",
fn: function () {
console.log("普通对象的方法")
}
};
console.log(obj.key);
console.log(obj["key"]);
// 1.key的类型为字符串类型
// 结论:
// js支持的标识符可以省略引号, 反之不可以省略
// 不支持的标识符访问方式: 不可以采用.语法,需要采用[]语法,eg:obj["background-color"] var obj1 = {
"name": "obj1",
// key有时候会出现js不能直接支持的标识符书写方式
// 需求: obj1用来描述页面标签的各种颜色
color: "red",
// "color": "red",
"background-color": "yellow"
}
console.log(obj1.name);
console.log(obj1["name"]);
console.log(obj1.color);
// obj1.background = 12;
// color = 10;
console.log(obj1["background-color"]); // 2. 对象可以任意添加或删除属性
var obj2 = {
name: "obj2"
};
console.log(obj2);
// 删除属性
delete obj2.name;
console.log(obj2);
// 添加属性
obj2.age = 8;
console.log(obj2); // 拓展: 获取的页面元素就是标签对象, 可以对其添加任意属性
var ele = document.querySelector('.ele');
console.log(ele.info); // 直接使用无值, 原因ele并没有添加该属性
ele.info = "添加的属性信息"; // 添加属性
console.log(ele.info); // 添加属性后就可以正常方式添加的属性值
delete ele.info; // 删除操作
console.log(ele.info); // 删除后属性又会消失 // 构造函数
function Perple(name, age) {
this.name = name;
this.age = age;
this.fn = function () {
console.log("fn")
}
}
// 实例化对象
var p = new Perple("张三", 18);
p.fn(); // ES6
class Student {
constructor (name, age) {
this.name = name;
this.age = age;
}
fn () {
console.log("fn")
}
}
var s = new Student("张三", 18);
s.fn(); </script>
<script>
// getElementById只能由document调用
var ele = document.getElementsByClassName("ele")[0];
console.log(ele);
ele = document.querySelector(".ele");
console.log(ele);
ele = document.querySelectorAll(".ele")[0];
console.log(ele); // 该添加属性的方式只映射到js代码中
ele.index = 123;
console.log(ele.index); // js如何操作元素(页面标签)的全局属性, 映射到html代码中
ele = document.querySelector('[alert]'); // 通过全局属性获取元素
console.log(ele);
// 获取全局属性值
var info = ele.getAttribute('alert');
console.log(info);
// 修改全局属性值
ele.setAttribute('alert', 'no ok');
// 添加全局属性值(映射到html代码中) => 结合CSS来控制页面标签的样式
ele.setAttribute('key', 'value'); </script>
</html>

事件参数event

存放事件信息的回调参数

在触发DOM上某个事件时,会产生一个事件对象event,这个对象包含着所有事件有关的信息(导致事件的元素、事件的类型、与特定事件相关的信息)
所有浏览器都支持Event对象,但支持方式不同
IE中的事件对象:window.event

阻止事件冒泡 

DOM中提供stopPropagation()方法,但IE不支持,使用event对象在事件函数中调用就行
IE中提供的是,cancelBubble属性,默认为false,当它设置为true时,就是阻止事件冒泡,也是用event对象在事件函数中调用 jQuery中提供了stopPropagation()方法来停止事件冒泡,当需要时,只需用用event对象来调用就行,即event.stopPropagation(); 默认行为 阻止默认行为
DOM中提供preventDefault()方法来取消事件默认行为,但是只有当cancelable属性设置为true的事件,才可以使用preventDefault()来取消事件默认行为,使用event对象在事件函数中调用就行
IE中提供的是returnValue属性,默认为true,当它设置为false时,就是取消事件默认行为,也是用event对象在事件函数中调用
jQuery中提供了preventDefault()方法来阻止元素的默认行为,只需要用event对象来调用就好,即event.preventDefault()
如果想同时对事件对象停止冒泡和默认行为,可以在事件处理函数中返回false。这是对事件对象同时调用stopPropagation()方法和preventDefault()方法的一种简写方式 

事件注意点

1、event代表事件的状态,例如触发event对象的元素、鼠标的位置及状态、按下的键等等;
2、event对象只在事件发生的过程中才有效。
firefox里的event跟IE里的不同,IE里的是全局变量,随时可用;
firefox里的要用参数引导才能用,是运行时的临时变量 在IE/Opera中是window.event,在Firefox中是event;
而事件的对象,在IE中是window.event.srcElement,在Firefox中是event.target,Opera中两者都可用

处理冒泡与默认事件

事件的冒泡:父子都具有点击事件,不处理的话,点击子级也会出发父级的点击事件

如果提供了事件对象,则这是一个非IE浏览器
if ( e && e.stopPropagation )
因此它支持W3C的stopPropagation()方法
e.stopPropagation();
else
否则,我们需要使用IE的方式来取消事件冒泡
window.event.cancelBubble = true;
return false;

处理冒泡实例

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件对象</title>
<style>
body {
margin: 0;
}
.box {
background-color: pink;
}
.sup {
width: 200px;
height: 200px;
background-color: red;
}
.sub {
width: 100px;
height: 100px;
background-color: orange;
}
</style>
</head>
<body>
<div class="box">12345</div> <div class="sup">
<div class="sub"></div>
</div> <a href="https://www.baidu.com">只想相应点击事件</a>
</body>
<script>
var box = document.querySelector('.box');
// 事件的钩子函数, 系统回调时传递了一个值, 该值为事件对象
box.onclick = function (ev) { // 回调函数
console.log(ev)
// 特殊按键 altKey | shiftKey | ctrlKey
console.log(ev.altKey)
// 鼠标的点击点
console.log(ev.clientX, ev.clientY)
}
</script>
<script>
var sup = document.querySelector('.sup');
var sub = document.querySelector('.sub'); // 事件默认有冒泡, 子级相应事件后,会将事件传递给父级,如果父级有相同事件,也会被激活, 最终传递给document
sub.onclick = function (ev) {
console.log(ev);
// 取消冒泡, 当自身处理事件后, 该事件就处理完毕, 结束, 不再向上传递
ev.cancelBubble = true;
console.log("子级被点击了")
};
sup.onclick = function () {
console.log("父级被点击了")
};
document.onclick = function () {
console.log("文档被点击了")
}
</script>
</html>

事件默认行为:当一个事件发生时浏览器自己会做的事情

如果提供了事件对象,则这是一个非IE浏览器
if ( e && e.preventDefault )
阻止默认浏览器动作(W3C)
e.preventDefault();
else
IE中阻止函数器默认动作的方式
window.event.returnValue = false;
return false; 既然return false 和 e.preventDefault()都是一样的效果,那它们有区别吗?当然有
仅仅是在HTML事件属性 和 DOM0级事件处理方法中 才能通过返回 return false 的形式组织事件宿主的默认行为

处理默认事件实例

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件对象</title>
<style>
body {
margin: 0;
}
.box {
background-color: pink;
}
.sup {
width: 200px;
height: 200px;
background-color: red;
}
.sub {
width: 100px;
height: 100px;
background-color: orange;
}
</style>
</head>
<body>
<div class="box">12345</div> <div class="sup">
<div class="sub"></div>
</div> <a href="https://www.baidu.com">只想相应点击事件</a>
</body>
<script>
var box = document.querySelector('.box');
// 事件的钩子函数, 系统回调时传递了一个值, 该值为事件对象
box.onclick = function (ev) { // 回调函数
console.log(ev)
// 特殊按键 altKey | shiftKey | ctrlKey
console.log(ev.altKey)
// 鼠标的点击点
console.log(ev.clientX, ev.clientY)
}
</script>
<script>
// 默认事件
var aBtn = document.querySelector('a');
aBtn.onclick = function (ev) {
ev.cancelBubble = true;
console.log("a被点击了");
// 手动转跳页面
open('https://www.oldboyedu.com', '_self');
// a标签默认会完成转跳, 如果取消默认事件
return false;
} </script>
</html>

再补充一些

默认操作 具体指的是什么呢?
(1)把单击事件处理程序注册到一个锚元素,而不是一个外层的<div>上,那么就要面对另外一个问题:当用户单击链接时,浏览器会加载一个新页面。

(2)当用户在编辑完表单后按下回车键时,会触发表单的submit事件,在此事件发生后,表单提交才会真正发生。
这种行为与我们讨论的事件处理程序不是同一个概念,它是单击标签元素的默认操作。

如果我们不希望执行这种默认操作,那么在事件对象上调用.stopPropagation()方法也无济于事,因为默认操作不是在正常的事件传播流中发生的
在这种情况下,处理方法有:

1、w3c的方法是e.preventDefault(),IE则是使用e.returnValue = false;
preventDefault它是事件对象(Event)的一个方法,作用是取消一个目标元素的默认行为。既然是说默认行为,当然是元素必须有默认行为才能被取消,如果元素本身就没有默认行为,调用当然就无效了。什么元素有默认行为呢?如链接<a>,提交按钮<input type=”submit”>等。当Event 对象的 cancelable为false时,表示没有默认行为,这时即使有默认行为,调用preventDefault也是不会起作用的。
1 <a href="http://www.cnblogs.com/yycode/" id="testA" >caibaojian.com</a> var a = document.getElementById("testA");
a.onclick =function(e){
if(e.preventDefault){
e.preventDefault();//
}else{
window.event.returnValue = false;//IE
     //注意:这个地方是无法用return false代替的
     //return false只能取消元素
}
} 2、return false;
javascript的return false只会阻止默认行为,而是用jQuery的话则既阻止默认行为又防止对象冒泡

常见事件

鼠标事件

var box = document.querySelector('.box');

1. 点击事件
box.onclick = function () {
console.log("单击");
};
2. 双击事件(应用场景不广)
box.ondblclick = function () {
console.log("双击");
};
3. 鼠标右键
box.oncontextmenu = function () {
console.log("右键了");
return false;
};
4. 鼠标悬浮 | 移动 | 按下 | 抬起 | 离开
box.onmouseover = function () {
console.log("悬浮");
};
box.onmousemove = function () {
console.log("移动");
};
box.onmousedown = function () {
console.log("按下");
};
box.onmouseup = function () {
console.log("抬起");
};
box.onmouseout = function () {
console.log("离开");
} 事件参数ev
ev.clientX:点击点X坐标
ev.clientY:点击点Y坐标

over | out   VS   enter | leave

总结:
1. 将子级与父级分开考虑, 大家都有各自的悬浮离开事件, 采用 over | out 组合
2. 将子级纳入父级考虑范围, 也就是只有父级去相应悬浮离开事件, 采用 enter | leave 组合
3. 单独考虑一个盒子的悬浮离开事件, 两套均可以 特性
从父级移至子级, 会触发out事件, 紧接着触发子级的over事件, 并可以冒泡给父级 从父级移至子级, leave事件并不会触发, 它认为子级是属于父级的一部分, enter事件, 也不会再次触发 悬浮子级:
sub over => sup over 支持冒泡
sup enter => sub enter 不支持冒泡

键盘事件

键盘事件
onkeydown:键盘按下会触发,长按持续触发
onkeyup:键盘抬起 事件参数ev ev.keyCode:按键编号
ev.altKey:alt特殊按键
ev.ctrlKey:ctrl特殊按键
ev.shiftKey:shift特殊按键 <head>
<meta charset="UTF-8">
<title>键盘事件</title>
<style>
.box {
width: 100px;
height: 100px;
background: orange;
position: absolute;
top: 0;
left: 0;
}
</style>
</head>
<body>
<div class="box"></div>
</body>
<script>
// 键盘长按会一直触发按下事件
document.onkeydown = function (ev) {
console.log(ev);
// 按下的键盘编号
console.log("按下", ev.keyCode);
// console.log(ev.which);
}
document.onkeyup = function (ev) {
console.log("抬起", ev.keyCode);
} // 左上右下: 37-40
var box = document.querySelector('.box');
document.onkeydown = function (ev) {
switch (ev.keyCode) {
case 37:
box.style.left = box.offsetLeft - 10 + 'px';
break;
case 38:
box.style.top = box.offsetTop - 10 + 'px';
break;
case 39:
box.style.left = box.offsetLeft + 10 + 'px';
break;
case 40:
box.style.top = box.offsetTop + 10 + 'px';
break;
}
}
</script>
</html>

表单事件

onfocus:获取焦点
onblur:失去焦点
onselect:文本被选中
oninput:值改变
onchange:值改变,且需要在失去焦点后才能触发
onsubmit:表单默认提交事件

文档事件

文档事件由window调用
onload:页面加载完毕触发
onbeforeunload:页面退出或刷新警告,需要设置回调函数返回值,返回值随意

图片事件

onerror:图片加载失败

页面事件

onscroll:页面滚动
onresize:页面尺寸调整
window.scrollY:页面下滚距离

文档页面事件运用实例

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>其他事件</title>
<script>
// 当页面加载完毕之后再回调
window.onload = function () {
var box = document.querySelector('.box');
console.log(box);
} // 页面滚动可以设置给 window | document
var isShow = false;
window.onscroll = function () {
console.log(window.scrollY);
if (window.scrollY >= 1200) {
if (!isShow) {
console.log("将返回Top按钮显示");
isShow = true;
}
} else {
if (isShow) {
isShow = false;
}
}
}
</script>
</head>
<body>
<div class="box"></div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</body> </html>

JS选择器

getElement系列

通过id名获取唯一满足条件的页面元素

document.getElementById('id名');
该方法只能由document调用
任何HTML元素可以有一个id属性,在文档中该值必须唯一
若浏览器中出现多个id名的情况,CSS样式对所有该id名的元素都生效,但javascript脚本仅对第一个出现该id名的元素生效。
getElementById()该方法接收一个参数:要取得元素的id,若找到则返回该元素,若不存在则返回null
注意:document.getElementById方法的内部实现需要用到this,这个this本来被期望指向document 跨浏览器兼容
1:在ie7中,使用getElementById()的时候,接收的参数id不区分大小写。
2:在表单元素中,如果表单设置有name属性,其name属性会被当做id识别出来。
3:id是唯一的,但name属性并不是唯一的。具有该名称的隐式全局变量会引用一个类数组对象,包括所有该命名的元素

通过class名获取所有满足条件的页面元素

document.getElementsByClassName('class名');
该方法可以由document及任意页面元素对象调用
document.getElementsByClass("class1
class2")可以拿到同时拥有class1和class2的元素,中间用空格隔开,不区分class1和class2的顺序。 兼容性:IE8及其以下版本的浏览器未实现getElementsByClassName方法
返回值为HTMLCollection (一个类数组结果的对象,使用方式同数组)
没有匹配到任何结果返回空HTMLCollection对象 ([]) 

通过name属性获取元素

getElementsByName(返回值是一个nodeList集合(区别于Array),可作用于Dom元素)
getElementsByName()方法接收一个参数,即要取得元素的name值。 document.getElementsByName("Name");Name为要获取元素的name属性值,这个方法一般适用于提交表单数据,当
元素为form、img、iframe、applet、embed、object的时候设置name属性时,会自动在Document对象中创建以该
name属性值命名的属性。
所以可以通过document.domName引用相应的dom对象。 在ie9中,getElementsByName()只对表单元素起作用。
IE9-浏览器中使用getElementsByName()方法也会返回id属性匹配的元素。因此,不要将name和id属性设置为相同的值。

通过tag名获取所有满足条件的页面元素

document.getElementsByTagName('tag名');
该方法可以由document及任意页面元素对象调用
返回值为HTMLCollection (一个类数组结果的对象,使用方式同数组)
没有匹配到任何结果返回空HTMLCollection对象 ([]) 
可以使用方括号语法或item()方法来访问类数组对象中的项,length属性表示对象中元素的数量。
[注意]通过getElementsByTagName()方法取得的类数组对象有一个namedItem()方法,可以通过元素的name属性取得集合中的第一个值。safari和IE不支持该方法。document.getElementsByTagName("*")表示匹配文档的所有元素

querySelect系列

获取第一个匹配到的页面元素

document.querySelector('css语法选择器');
该方法可以由document及任意页面对象调用 

获取所有匹配到的页面元素

document.querySelectorAll('css语法选择器');
该方法可以由document及任意页面对象调用
返回值为NodeList (一个类数组结果的对象,使用方式同数组)
没有匹配到任何结果返回空NodeList对象 ([])

id名

可以通过id名直接获取对应的页面元素对象,但是不建议使用

js选择器运用实例

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>js选择器</title>
<style>
#d {
color: red;
}
</style>
</head>
<body id="bd">
<!--注释-->
<div id="d" class="dd">我是ddd111</div>
<div id="d" class="dd">我是ddd222</div> <div class="sup1">
<div id="div"></div>
</div>
<div class="sup2">
<div id="div"></div>
</div>
</body>
<script>
// 节点(了解): 在文档(document)中出现的所有内容都是document中的节点
// 节点(node): 标签节点(元素element) | 注释节点 | 文本节点 | <!doctype>节点
console.log([bd]) // 文本 注释 文本 标签 文本 标签 文本 标签 文本 标签 文本
</script>
<script>
// js选择器: 将js与html建立起连接
// js中一般称标签为页面元素 // 1.直接通过id名进行匹配
console.log(d); // 两个都可以找到 // 2.getElement系列(最严谨)
// 所有显示在页面中的内容(展现给用户看的), 都是属于文档(document)对象的内容, 存放在文档中
// console.log(document)
// 获取文档中的标签 => document对象通过.语法去获取具体的目标标签元素
// ① id
var div = document.getElementById('d'); // 检索得到页面中出现的第一个满足条件的目标
console.log(">>>", div); var body = document.getElementById("bd");
console.log(body); // 注: getElementById该方法只能由document来调用
// 原因: 我们需要保证一个文档中一个id只能出现一次, document检索的就是文档,
// 而某父级标签只能检索自身标签内部区域, document可以保证文档中只能一个id
// 只出现一次,某父级标签只能保证自身内部区域id不重复,能不能保证与外界不重复?
// 不能, 所以从安全角度出发, 获取唯一对象的getElementById方法只能由能确定唯一id的
// 对象来调用, 能被document调用, 不能被sup来调用 // ② 类名
var divs = document.getElementsByClassName('dd');
console.log(divs);
// 两个div在body之中, 上方已经获取了body, 那能否通过body来获取body中的div
var divs1 = body.getElementsByClassName('dd');
console.log(divs1); // ③ 标签名
var divs = document.getElementsByTagName('div');
console.log(divs) console.log('--------------------------------------------------'); // 3.querySelector系列(最方便)
// 参数: 就是css选择器语法
// querySelector检索第一个
var div = document.querySelector('body > .dd');
console.log(div); // querySelectorAll检索所有满足结果
var divs = document.querySelectorAll('body > .dd');
console.log(divs);
var divs = body.querySelectorAll('.dd');
console.log(divs) var divs = body.querySelectorAll('#d'); // 不严谨
console.log(divs) </script>
</html>

选择器分类

1. ID选择器

使用ID选择器时,需在前面添加“#”,区分大小写,语法如下:document.querySelector('#id'); //等同于document.getElementById('id')

2. 元素选择器

元素选择器通过指定的标签查询元素,此时querySelectorAll等同于getElementsByTagName,语法如下:document.querySelectorAll('a'); //获取页面上的所有a元素并返回元素

3. 样式类选择器

使用元素的样式类获取一个或一类元素,样式名字前使用“.”(英文句号)开头,语法如下:document.querySelectorAll('.btn'); //获取所有样式类中包含btn类名的元素

4. 分组选择器

使用querySelectorAll不仅可以获取一个或一类元素,还可以同时获取其他类别元素,两种类型之间使用逗号隔开,语法如下:document.querySelectorAll('a,p');
//获取页面上所有a元素和p元素,并通过一个列表返回document.querySelectorAll('.btn,.txt'); //获取页面上所有包含btn和txt样式类名的元素 5. 属性选择器 获取页面上包含指定属性的元素,属性名称可以是元素原生属性和用户自定义属性,语法如下:document.querySelectorAll('a[target="_blank"]');
//获取页面上所有target属性为_blank的a元素document.querySelectorAll('img[data-id]'); //获取页面上所有带有自定义属性data-id的img元素 6. 后代选择器 主要用于选择作为某元素后代的元素,规则左边的选择器一端包含两个或多个用空格分隔的选择器,如div a可以理解为查找所有被div包围的所有a元素,语法如下:document.querySelectorAll('div a');
//获取页面上所有被div包含的a元素document.querySelectorAll('div .btn'); //获取页面上所有被div包含的带有btn样式类名的元素 7. 子元素选择器 后代选择器会将元素底下的所有相关元素都搜索出来,如果想进一步缩小范围,可以使用子元素选择器,只会选择某个元素的一级子元素,子元素用“>”(大于号)表示,代码如下:
<html> <div id="first"> <div></div> <div></div> </div></html> <script> document.querySelectorAll('html>div'); //只返回一个id为first的div元素</script> 8. 相邻兄弟选择器(比较少用) 选择紧接在另一个元素后的元素,而且两者有相同的父元素,相邻兄弟选择器使用“+”(加号),代码如下:
<div> <div></div> <div></div></div><p id="p1"></p><p id="p2"></p><script> document.querySelectorAll('div+p');
//只返回一个id为p1的p元素</script> 9. 伪类选择器 “:first-child”表示选择元素的第一个子元素,“:last-child”表示选择元素的最后一个子元素,“:nth-child(n)”表示选择元素的第n个子元素。“:first-child”的使用例子,代码如下:
<div> <p id="p1"></p> <p id="p2"></p></div> <script> document.querySelectorAll('p:first-child'); //只返回一个id为p1的p元素</script>

闭包

function outer() {
var data = {}
function inner() {
return data;
}
return inner;
}

闭包目的:不允许提升变量作用域时,该函数的局部变量需要被其他函数使用
闭包本质:函数的嵌套,内层函数称之为闭包
闭包的解决案例:①影响局部变量的生命周期,持久化局部变量;②解决变量污染

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>闭包</title>
</head>
<body>
闭包
</body>
<script>
// 了解知识点
// 闭包: 局部的函数(被一个函数包裹的函数)
// 为什么使用闭包:
// 1.一个函数要使用另一个函数的局部变量
// 2.闭包会持久化包裹自身的函数的局部变量
// 3.解决循环绑定 // 函数的嵌套定义
function outer() {
var num = 10;
function inner() {
// 1.在inner函数中,使用了outer的局部变量num
return num;
}
return inner;
}
var innerFn = outer();
// 2.借助闭包,将局部变量num的生命周期提升了
var num = innerFn();
console.log(num); </script>
</html>

循环绑定

.html文件

<ul>
<li>列表项</li>
<li>列表项</li>
<li>列表项</li>
</ul>

.js文件

var lis = document.querySelector('li');
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = function () {
// 打印列表项的索引
console.log(i);
}
}

会发生变量污染

解决方法

1 获取局部作用域解决   2  闭包解决  3  对象属性解决

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>循环绑定</title>
</head>
<body>
<div class="box">0000000000000000001</div>
<div class="box">0000000000000000002</div>
<div class="box">0000000000000000003</div>
</body>
<script>
var divs = document.querySelectorAll(".box");
/* 存在污染
for (var i = 0; i < divs.length; i++) {
// i = 0 | 1 | 2 | 3
// 循环绑定
divs[i].onclick = function () {
console.log("***", i)
}
}
// i = 3
console.log(">>>", i);
*/ /* 利用块级作用域解决
for (let i = 0; i < divs.length; i++) {
// {i=0 <= i} {i=1 <= i} {i=2 <= i}
// i = 3
// 循环绑定
divs[i].onclick = function () {
console.log("***", i)
}
} // for运行结束, i=3会被销毁
console.log(">>>", i)
*/ // 利用标签的属性解决
/*
for (var i = 0; i < divs.length; i++) {
divs[i].index = i;
divs[i].onclick = function () {
// console.log("###", i)
console.log(this.index)
}
}
*/ // 利用闭包处理循环绑定
for (var i = 0; i < divs.length; i++) {
(function () {
var index = i;
divs[index].onclick = function () {
console.log("###", index)
}
})()
/*
(function (index) {
divs[index].onclick = function () {
console.log("###", index)
}
})(i)
*/
/*
(function (i) {
divs[i].onclick = function () {
console.log("###", i)
}
})(i)
*/
} </script>
</html>

面向对象JS

属性与方法

var obj = {}; | var obj = new Object();

属性

obj.prop = "";

方法

obj.func = function () {}

删除属性与方法

delete obj.prop
delete obj.func

属性和方法实际使用

对象: 特征与行为的结合体, 是一个具象的实体

// js对象语法
var obj = {
// 属性
name: 'Zero',
// 方法
teach: function () {
console.log("教学");
}
};
// 对象使用属性与方法, 采用.语法
console.log(obj.name);
obj.teach();

JS中中括号([ ])与 .

中括号运算符总是能代替点运算符。但点运算符却不一定能全部代替中括号运算符
中括号运算符可以用字符串变量的内容作为属性名。点运算符不能
中括号运算符可以用纯数字为属性名。点运算符不能
中括号运算符可以用js的关键字和保留字作为属性名。点运算符不能

下面的例子中,a.b表示对象a的属性b,既可以设置也可以读取

object[key]=>key为常量时,object[key]等价于object.key,例如:a.b == a['b'] 

特殊的,object[key] 中key为变量时,只能用中括号形式

var a = {};
// a.b = 1;
a['b'] = 1;
c = a.b;
// c = a['b'];
alert(c);

标识符是否合法对两种用法的影响

var obj = {};
// 为obj添加一个属性name,name是合法的标识符,即也可以通过obj.name方式来定义 obj['name'] = 'jack'; // 为obj添加一个属性2a,2a不是合法的标识符(不能以数字开头),不能通过obj.2a来定义 obj['2a'] = 'test'; var obj = {name:'jack'};
obj['2a'] = 'test';
obj['name']; // --> jack
obj['2a']; // --> test (不能通过obj.2a获取)

总结:常量用点,变量就用中括号

运算符左侧应当是一个表达式,它返回一个对象。
对于点(.)来说,右侧必须是一个以属性名称命名的简单标识符。
对于方括号([])来说,方括号里必须是一个计算结果为字符串的表达式,这个字符串就是属性的名字

当通过点运算符(.)方法对象属性时,属性名用一个标识符来表示。标识符必须直接出现在js程序中,它们不是数据类型,因此程序无法修改它们。
反过来讲,当通过[]来方式对象的属性时,属性名通过字符串表示。字符串是js的数据类型,在程序运行时可以修改和创建它们

<script type="text/javascript">
var addr = "";
for(i=0;i<4;i++){
addr += cutomer["address" + i] + "\n";
}
</script>

这段代码读取customer对象的address0,adddress1,address2,adddress3属性,并将他们连接起来

类字典结构使用

结构

var dict = {name: "zero", age: 18}

拓展

var dict = {"my-name": "zero", fn: function () {}, fun () {}}

使用

dict.name | dict["my-name"] | dict.fn()

构造函数(ES5)

// 构造函数: 声明与普通函数一样, 只是函数名采用大驼峰命名规则
function Person(name) { // 类似于python中的类一样来使用
// 构造函数内部属性方式不同于普通函数
this.name = name; // this代表Person构造函数实例化出的所有具体对象中的某一个
this.teach = function () {
console.log(this.name + "正在教学");
}
}
// 如何使用构造函数中的属性与方法
// 1. 通过构造函数实例化出具体对象
// 2. 通过对象.语法调用属性与方法
var p1 = new Person("杨虎虎"); // name: 杨虎虎
var p2 = new Person("刘xx"); // name: 刘xx
console.log(p1.name);
console.log(p2.name);
p1.teach();
p2.teach(); 为什么要用new? new 会创建 pre 的对象,
但是没有 new 的话就没有没有可返回的值或对象了,所以是 undefined。
如果不想new 新的对象的话,可以在 pre 的方法里 返回一个值或对象。
function pre(){
this.radius = Math.random();
return this.radius;
} 加 new 会把这个函数当作是一个构造器,返回一个对象。
不加的话,就是调用一个普通的函数,结果视函数返回值而定。
有new,就返回对象,不管函数返回值如何。
无new,就看函数返回值。
构造函数最好返回 this 或者无返回值, 否则容易混淆。

类及继承(ES6)

// ES6
// 引入了类
class Student { // 类, 可以实例化对象, 但实例化出的对象需要加以区分
// 需要构造器(构造函数)来完成对象的声明与初始化
// ES6规定方法的语法
constructor (name) {
// 属性在构造器中声明并完成初始化
this.name = name;
}
// 类中规定普通方法
study () {
console.log(this.name + "正在学习");
}
// 类方法
static fn() {
console.log("我是类方法")
}
}
// 1.实例化类的对象
let stu1 = new Student("嘿嘿");
// 2.使用属性与方法
console.log(stu1.name);
stu1.study(); let stu2 = new Student("嘻嘻");
console.log(stu2.name);
stu2.study(); Student.fn() <script>
// 类方法
class Tool { // 功能类(工具类)中的方法都定义为类方法
static max (num1, num2) {
return num1 > num2 ? num1 : num2;
}
}
// 通过Tool类来求两个数中的大值, 需要Tool类的对象出现吗? 不需要 => 功能有类直接使用
console.log(Tool.max(666, 888)); // throw "自定义异常";
// console.log("上面如果出现了异常, 逻辑将会被强制停止");
// var num = 10 / 0;
// console.log(num)
</script>