>### A.今天学什么?
#### 1.定时器timer
- ##### 1.1 setTimeout --> 超时调用
- 语法:setTimeout(func,time); 时间单位为毫秒,间隔一段时间触发函数,只触发一次
- ##### 1.2 setInterval -- > 重复调用
- 语法:setInterval(func,time); 每间隔一段时间触发
```
// body
<body>
<script>
// setTimeout --> 超时调用
// 语法
// setTimeout(func,time) 时间单位为毫秒
// 间隔一段时间触发函数,只触发一次
setTimeout(function () {
alert("测试");
},2000);
/*
setInterval -- > 重复调用
语法
setInterval(func,time);
每间隔一段时间触发*/
setInterval(function () {
alert("测试")
},2000)
</script>
</body>
```
- ##### 1.3 使用setTimeout实现setInterval
- 核心:递归调用
```
// body
<body>
<script>
// 使用setTimeout实现setInterval
// 相当于无限递归
function go() {
alert("hello world");
setTimeout(go,1000);
}
go();
</script>
</body>
```
#### 2.制作一个input框和按钮,输入后,将内容放入ul内
- ##### 2.1使用方法
- 获取元素对象
- onclick事件
- 对象.value属性 ---> 输入内容
- 创建元素对象
- 对象.innerHTML属性 ---> 标签内内容
```
// body
<body>
<div>
<input type="text" id="txt" />
<button id="add">添加</button>
</div>
<ul id="parent">
</ul>
<script>
var txt = document.getElementById("txt");
var add = document.getElementById("add");
var parent = document.getElementById("parent");
add.onclick = function () {
var value = txt.value;
// 提交后,将其清空
txt.value = ""; // value是输入框里的值
var li = document.createElement("li");
li.innerHTML = value; // innerHTML是元素内的内容
console.log(li);
parent.appendChild(li);
}
</script>
</body>
```
#### 3.DOM获取元素父节点
- ##### 3.1方法介绍
- node.parentNode --> 获取父元素(亲爹~),比如 body>ul>li(这里的>代表上下父子关系),li.parentNode,不会获取body,只会获取ul。
```
// body
<body>
<div class="parent">
<p class="child">hello world</p>
</div>
<script>
// node.parentNode --> 获取父元素(亲爹~)
var p = document.getElementsByClassName("child")[0];
var parent = p.parentNode;
console.log(parent);
</script>
</body>
```
- ##### 3.2实例:点击删除,删掉父节点
- 利用for循环给a标签加上onclick事件
- 注意a标签内href加#,或者onclick事件最后return false;终止a标签的默认跳转。否则会造成,删除又恢复BUG
```
// body
<body>
<ul>
<li>小米<a href="#">删除</a></li>
<li>华为<a href="#">删除</a></li>
<li>苹果<a href="#">删除</a></li>
</ul>
<script>
var shows = document.getElementsByTagName("a");
for (var i = 0;i <shows.length;i++){
shows[i].onclick = function () {
// this指正在执行事件的当前对象
this.parentNode.style.display = "none";
// 阻止a标签的默认跳转事件,否则会发生
// 删掉又恢复了的情况
// 或者给a标签 href 给一个 #,表示当前页面,不会跳转。
return false;
}
}
</script>
</body>
```
#### 4.获取子节点
- ##### 4.1 childNodes --> 获取所有类型的子节点
- childNodes --> 获取所有类型的子节点,```
// <ul id="parent">
// <li>```
// 之间的换行符也会被当成一个文本节点
- ##### 4.2 children --> 获取所有的元素子节点,IE9以后
- 只会获取元素节点,不会获取文本节点。IE9之后貌似才支持,所以不要用IE~~
- ##### 4.3 获取第一个、最后一个子节点
- firstChild --> 获取第一个子节点
- lastChild --> 获取最后一个子节点
- ##### 4.4 获取第一个、最后一个元素子节点
- firstElementChild --> 获取第一个元素子节点
- lastElementChild --> 获取最后一个元素子节点
```
// body
<body>
<ul id="parent">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
// childNodes --> 获取所有类型的子节点,
// <ul id="parent">
// <li>
// 之间的换行符也会被当成一个文本节点
var parent = document.getElementById("parent");
var childNodes = parent.childNodes;
console.log("parent的childNodes长度为"+childNodes.length);
// nodeType值为1时,是元素节点
// 文本节点不能设置背景颜色,会报错,所以需要过滤
for(var i = 0;i < childNodes.length;i++){
if(childNodes[i].nodeType === 1){
childNodes[i].style.backgroundColor = "red";
}
}
// children --> 获取所有的元素子节点,IE9以后
var childs = parent.children;
console.log("parent的children长度为"+childs.length);
// firstChild --> 获取第一个子节点
// lastChild --> 获取最后一个子节点
var fc = parent.firstChild;
console.log(fc);
var lc = parent.lastChild;
console.log(lc);
// firstElementChild --> 获取第一个元素子节点
// lastElementChild --> 获取最后一个元素子节点
var fec = parent.firstElementChild;
console.log(fec);
var lec = parent.lastElementChild;
console.log(lec);
</script>
</body>
```
#### 5.获取兄弟节点
- ##### 5.1获取兄弟节点--所有类型的节点
- node.previousSibling -->获取前面的兄弟节点
- node.nextSibling --> 获取后面的兄弟节点
- ##### 5.2获取兄弟元素节点
- node.previousElementSibling --> 获取前面的兄弟元素节点
- node.nextElementSibling --> 获取后面的兄弟元素节点
```
// body
<body>
<div>
<p>hello world 01</p>
<p id="test">hello my friend 02</p>
<p>hello chunjue 03</p>
</div>
<script>
/*node.previousSibling -->获取前面的兄弟节点
node.nextSibling --> 获取后面的兄弟节点*/
var test = document.getElementById("test");
var pSibling = test.previousSibling;
var nSibling = test.nextSibling;
console.log("test.previousSibling"+pSibling);
console.log("test.nextSibling"+nSibling);
/*node.previousElementSibling --> 获取前面的兄弟元素节点
node.nextElementSibling --> 获取后面的兄弟元素节点*/
var peSibling = test.previousElementSibling;
var neSibling = test.nextElementSibling;
</script>
</body>
```
#### 6.offset属性
- ##### 6.1 特点
- 只读,无法更改
- ##### 6.2 获取元素偏移量
- element.offsetLeft --> 获取元素的左偏移量
- element.offsetTop --> 获取元素的上偏移量
- ##### 6.3 获取元素的宽高
- element.offsetWidth --> 获取元素的宽度
- element.offsetHeight --> 获取元素的高度
```
// css
<style>
*{margin: 0;padding: 0}
div{
width: 100px;
height: 100px;
background-color: red;
margin: 100px;
position: absolute;
left: 100px;
padding: 20px;
border: 10px solid #333;
}
</style>
// body
<body>
<div id="test">
</div>
<script>
// 特点:只读属性,无法修改
var test = document.getElementById("test");
// element.offsetLeft --> 获取元素的左偏移量
// element.offsetTop --> 获取元素的上偏移量
var offL = test.offsetLeft;
var offT = test.offsetTop;
// test.offsetLeft = "1000px"; 只读属性,无法修改
console.log("test.offsetLeft"+offL);
console.log("test.offsetTop"+offT);
// element.offsetWidth --> 获取元素的宽度
// element.offsetHeight --> 获取元素的高度
var offW = test.offsetWidth;
var offH = test.offsetHeight;
// test.offsetWidth = "500px"; 只读属性,无法修改
console.log("test.offsetWidth"+offW);
console.log("test.offsetHeight"+offH);
</script>
</body>
```
#### 7.属性的操作--Attribute
- ##### 7.1 设置属性值
- 设置属性值 --> element.setAttribute("属性名", "属性值");
- 使用设置属性值的方式来设置样式值
- test.setAttribute("style","color:red"); style也是属性,内联样式
- ##### 7.2 获取属性值
- 获取属性值 --> element.getAttribute("属性名");
- var cValue = test.getAttribute("class");
- ##### 7.3 移除属性值
- 移除属性值 --> removeAttribute("属性名");
- test.removeAttribute("class");
```
// body
<body>
<p id="test" class="one">hello world</p>
<script>
// 设置属性值 --> element.setAttribute("属性名", "属性值");
// 使用设置属性值的方式来设置样式值
var test = document.getElementById("test");
test.setAttribute("style","color:red");
// 获取属性值 --> element.getAttribute("属性名");
var cValue = test.getAttribute("class");
console.log(cValue);
// 将p标签的class设置为two
test.setAttribute("class","two");
console.log(test.getAttribute("class"));
// 移除属性值 --> removeAttribute("属性名");
test.removeAttribute("class");
</script>
</body>
```
- 7.4 利用设置属性方法,设置鼠标悬停提示
- title属性,鼠标悬停提示
```
// body
<body>
<p id="test">hello chunjue</p>
<script>
var test = document.getElementById("test");
// title属性,鼠标放上去会出现的那种提示
test.setAttribute("title","title");
</script>
</body>
```
#### 8.窗口宽高
- ##### 8.1 浏览器的宽高 -- 由窗口大小决定
- window.innerWidth; --> 浏览器宽度
- window.innerHeight; --> 浏览器高度
- ##### 8.2 文档元素的宽高 -- 和浏览器一样(目前来看
- document.documentElement.clientWidth; --> 文档元素宽度
- document.documentElement.clientHeight; --> 文档元素高度
- ##### 8.3 对象body的宽高 -- 由内部元素宽高决定
- document.body.clientWidth; --> 对象body宽度
- document.body.clientHeight; --> 对象body高度
- ##### 8.4 获取页面内容的宽高
- 如果浏览器显示内容小于内部元素宽高,则显示元素的宽高;如果大于内部元素的宽高,则显示浏览器宽高,不同浏览器显示不一样,不必纠结
- document.documentElement.scrollWidth; --> 页面内容宽度
- document.documentElement.scrollHeight; --> 页面内容高度
```
// css
<style>
*{margin: 0;padding: 0}
#test{
height: 300px;
background-color: red;
}
</style>
// body
<body>
<div id="test"></div>
<script>
// 浏览器的宽高 -- 由窗口大小决定
// window.innerWidth --> 浏览器宽度
// window.innerHeight --> 浏览器高度
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
console.log("浏览器宽度为"+windowWidth);
console.log("浏览器高度为"+windowHeight);
// 文档元素的宽高 -- 和浏览器一样
var dw = document.documentElement.clientWidth;
var dh = document.documentElement.clientHeight;
console.log("文档元素的宽度为"+dw);
console.log("文档元素的高度为"+dh);
// 对象body的宽高 -- 由内部元素宽高决定
var bw = document.body.clientWidth;
var bh = document.body.clientHeight;
console.log("body的宽度"+bw);
console.log("body的高度"+bh);
// 获取页面内容的宽高 -- 如果浏览器显示内容小于内部元素宽高,则显示元素的宽高
// 如果大于内部元素的宽高,则显示浏览器宽高,不同浏览器显示不一样,不必纠结
var dsw = document.documentElement.scrollWidth;
var dsh = document.documentElement.scrollHeight;
console.log("页面内容的宽为"+dsw);
console.log("页面内容的高位"+dsh);
</script>
</body>
```
#### 9.文档碎片
- ##### 9.1优点:提高渲染效率
- document.createDocumentFragment(); --> 创建文档碎片
- 是一个脱离文档流的碎片,相当于一个缓冲区
- 相当于一个缓冲区
```
// body
<body>
<ul id="parent">
</ul>
<button id="btn">btn</button>
<script>
// document.createDocumentFragment(); --> 文档碎片,优点:提高渲染效率
var btn = document.getElementById("btn");
var parent = document.getElementById("parent");
// 脱离文档流的碎片,相当于一个缓冲区
var frame = document.createDocumentFragment();
btn.onclick = function () {
for (var i = 0;i < 10;i++){
var li = document.createElement("li");
// 利用fragment缓冲,可以提升一定性能。
frame.appendChild(li);
}
parent.appendChild(frame);
}
</script>
</body>
```
#### 10.表格属性
- ##### 10.1表格属性与获取方法
- table.tHead --> 获取表格的标题部分
- table.tBodies --> 获取表格的主体部分,得到的是一个数组,因为表格可能有多个tbody
- tbody.rows --> 获取tbody每一行tr,得到的也是一个数组
- rows[n].cells[n] --> 获取第n行tr的第n个单元格td
- ##### 10.2利用js表格属性完成以下要求
- 1.标题的背景色变为 #eee
- 2.tbody下奇数行为 #ff2d51 偶数行为 #44cef6
```
// css
<style>
table,td,th{
border: 1px solid #333;
}
table{
width: 500px;
border-collapse: collapse;
line-height: 50px;
text-align: center;
}
</style>
// body
<body>
<table id="table">
<thead>
<tr>
<th>商城</th>
<th>手机</th>
</tr>
</thead>
<tbody>
<tr>
<td>京东商城</td>
<td>苹果手机</td>
</tr>
<tr>
<td>天猫</td>
<td>华为手机</td>
</tr>
<tr>
<td>拼多多</td>
<td>魅族手机</td>
</tr>
<tr>
<td>小米商城</td>
<td>小米</td>
</tr>
</tbody>
</table>
<script>
/*1.标题的背景色变为 #eee
2.tbody下奇数行为 #ff2d51 偶数行为 #44cef6*/
var table = document.getElementById("table");
// table.tHead --> 获取表格的标题部分
var thead = table.tHead;
// table.tBodies --> 获取表格的主体部分,得到的是一个数组,因为表格可能有多个tbody
var tbody = table.tBodies[0];
// tbody.rows --> 获取tbody每一行tr,得到的也是一个数组
var rows = tbody.rows;
// rows[n].cells[n] --> 获取第n行tr的第n个单元格td
var firstCell = rows[0].cells[0];
console.log(thead);
thead.style.backgroundColor = "#eee";
for (var i = 0;i < rows.length;i++){
if(i%2 === 0){
rows[i].style.backgroundColor = "#ff2d51";
}
else{
rows[i].style.backgroundColor = "#44cef6";
}
}
firstCell.innerHTML = "银泰百货";
</script>
</body>
```
- ##### 10.3动态添加表格主体内容
- 标题 -- 品牌,价格
- 两个input框分别输入品牌与价格,要求按下按钮,能添加到表格内
```
// css
<style>
table{
border: 1px solid #333;
width: 500px;
line-height: 50px;
border-collapse: collapse;
text-align: center;
margin-top: 30px;
}
th,td{
border: 1px solid #333;
}
</style>
// body
<body>
<div>
手机品牌<input type="text" id="phone" />
价格<input type="text" id="price" />
<button id="btn">添加</button>
</div>
<table id="table">
<thead>
<tr>
<th width="60%">品牌</th>
<th>价格</th>
</tr>
</thead>
<tbody>
<tr>
<td>苹果5</td>
<td>3000</td>
</tr>
</tbody>
</table>
<script>
var btn = document.getElementById("btn");
var phone = document.getElementById("phone");
var price = document.getElementById("price");
var tbody = document.getElementById("table").tBodies[0];
btn.onclick = function ( ) {
var tr = document.createElement("tr");
var td = document.createElement("td");
td.innerHTML = phone.value;
tr.appendChild(td);
var td1 = document.createElement("td");
td1.innerHTML = price.value;
tr.appendChild(td1);
console.log(tr);
tbody.appendChild(tr);
}
</script>
</body>
```
#### 11.函数function
- ##### 11.1定义函数的三种方法
- 1.直接定义函数 --> function funcName(args){方法体},可以在函数定义前就调用,但是不推荐
- 2.变量声明定义函数 --> var funcName = function(args){方法体},由于js的声明提前,不能在函数定义前调用,不推荐
- 3.构造函数的方式声明 --> var funcName = new Function("args","方法体"); 第一个参数为参数,第二个为函数表达式--更加不推荐
```
// body
<body>
<script>
// 1.直接定义函数
function go() {
console.log("hello world");
}
go(); // 在函数定义前面调用也可以,但是不推荐,还是按顺序式调用
// 2.变量声明定义函数 -- 会造成声明提前,这样的话就不能在定义函数之前调用
var one = function () {
console.log("one");
};
one();
// 3.构造函数的方式声明 -- 第一个参数为参数,第二个为函数表达式--更加不推荐
var two = new Function("two","console.log(two)");
two("aaa");
</script>
</body>
```
- ##### 11.2 ES6新的定义函数方法--箭头函数
- 定义方法:var funcName = (args)=>{方法体},ES6的箭头函数,ES5不支持
```
// body
<body>
<script>
var one = function () {
console.log("one")
};
// ES6箭头函数
var go = ()=>{
console.log("hello ES6");
}
go();
// 创建一个对象,其中有2个函数。
var obj = {
say:function () {
console.log("say");
},eat:()=>{
console.log("eat");
}
}
obj.eat();
</script>
</body>
```
- ##### 11.3 js函数的传参
- javaScript不同于java,定义函数参数列表有2个参数,但是执行函数时,甚至可以一个参数都不传,因此,javaScript不像java那样支持函数的重载
- 如果想实现类似函数重载的效果,需要用到javaScript特有的,函数中存在的arguments对象,其中存储了调用函数时传入的参数,然后根据其长度判断执行不同的方法体。
- 函数内部有一个arguments对象来管理函数传入的参数,然后可以根据arguments的长度来执行方法体
```
// body
<body>
<script>
// js中函数传不定参
function go(a,b) {
console.log(a);
console.log(b);
}
go(); // 不会报错,输出NaN
// 所以js中一般函数不能重载,后面的重名函数会覆盖前面的重名函数
// js中如何实现重载 使用arguments对象
// 函数内部有一个arguments对象来管理函数传入的参数,然后可以根据arguments的长度来执行方法体
function test() {
console.log(arguments);
console.log(arguments.length);
}
// 做一个重载函数的例子 -- 其实就是根据传入参数长度不同进入不同的if判断
function testFunc() {
if (arguments.length === 1){
console.log(arguments[0]);
}
else if (arguments.length === 2){
console.log(arguments[1]);
}
else{
console.log("hello chunjue");
}
}
</script>
</body>
```
#### 14.js基本类型和引用类型的区别
- ##### 14.1 javaScript这两种变量类型的区别,与java差不多
- 1.基本类型只传值
- 2.引用类型既传值也传址,两者指向同一个地址
```
// body
<body>
<script>
// 1.基本类型只传值
// 2.引用类型既传值也传址,两者指向同一个地址
var a = 10;
var b = a;
a = 15;
console.log(b); // 10
// 这时候,b还是10,不会随着a的改变而改变,因为基本类型都在栈里面,占据固定内存大小,是直接使用的。
// var arr1 = arr的时候,是让arr1指向了arr指向的地址,
// 如果修改该地址的引用类型变量,那么指向该地址的变量的值都会改变
var arr = [1,2,3];
var arr1 = arr;
arr[arr.length] = 4;
console.log(arr1); // [1,2,3,4]
// 对象也同理
var obj = {name:"依然"};
var yiran = obj;
obj.age = 21;
console.log(yiran.age);
</script>
</body>
```