1. JS作用域
1.1 全局作用域和局部作用域
-
-
函数内是局部作用域
-
全局变量可以直接在函数内修改和使用
-
变量,使用
var
是声明,没有var
是使用变量。 如果在函数内使用var
来声明变量,在函数内会覆盖同名的全局变量
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>作用域</title> </head> <body> <h1>作用域</h1> <hr> <script src="script.js"></script> <script> //全局作用域 var username = '小丽丽'; function demo() { //局部作用域 var age = 100; console.log(age); //局部变量 console.log(username); //实用全局作用域的变量 (全局变量) username = '小哈哈'; //不加var在局部直接修改 全局变量 } demo(); //函数调用 console.log(username); //全局变量在全局和局部均可以被引用 console.log(address) //我们在js文件中声明一个address全局变量,在此依然可以被引用 </script> <script> console.log(username) //只要是全局变量在哪都可以被引用 </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>局部作用域</title> </head> <body> <h1>局部作用域</h1> <hr> <script> var username = '小梅梅'; function demo(){ var username = '小丽丽'; console.log(username) //会先从自己的局部变量开始找,局部没有声明则找全局变量去找 } demo(); console.log(username); //全局不会去局部去找 </script> </body> </html>
1.2 变量提升
-
在变量声明之前 去使用变量 会得到 undefined ,而不是报错
-
函数内,如果声明了跟全局变量同名的局部变量, 在声明之前使用改变量,得到undefined( 该变量已经是局部的啦)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>变量提升</title> </head> <body> <script> console.log(age); //不会报错。 输出undefined 变量提升--------在变量定义之前去引用变量名 var age = 1000; console.log(age); //1000 //变量提升的变形 var user = '小丽丽'; function demo() { console.log(user); //undefined 变量提升-----之后就不会到全局去找 var user = '大丽丽'; //声明局部变量 user } demo(); </script> </body> </html>
1.3 作用域链
-
当一个作用域 使用某个变量时,先从本作用域中找, 如果没有去父作用域,再没有,父作用域的父作用域,一直到 全局作用域。 构成了一个作用域链
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>作用域链</title> </head> <body> <h1>作用域链</h1> <hr> <script> var age = 10; //全局 哪都能用 //demo再全局作用域中 function demo() { //再次声明age var age = 100; //嵌套函数 function fn() { var age = 1000; //再嵌套函数 function my() { console.log(age) var age = 10000; var address = '上海'; //在my函数的作用域中,在my中声明的变量,外部并不能引用 } my(); //调用函数 console.log(address); //fn函数的作用域 --中没有address没有声明address这个变量,其上包括全局也没有定义这个变量,所以会报错 } fn(); } demo(); </script> </body> </html>
1.4 闭包
-
通常需要 函数中 返回一个 函数
-
目的 把一个局部作用域的 数据 让外层的作用域使用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>闭包</title> </head> <body> <script> function demo () { function fn() { //这个作用域的 值 // 通过闭包的形式, 让外层作用域 可以使用 return 100; } return fn; } console.log(demo()()) </script> </body> </html>
1.5 ES6 新增一 块状作用域
-
let
关键字也可以声明变量,同var
一样 -
但是
let
关键字声明的变量,会在结构语句中产生 块状作用域 -
ES6建议 使用let代替 var
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>块状作用域</title> </head> <body> <script> // let也是声明变量,但是它和var还是有区别的,区别见下面代码 for (var i = 1; i <= 10; i ++) { console.log(i); } console.log(''); console.log(i); // i 在全局作用域,所以在此可以被引用 console.log(''); for (let a = 1; a <= 3; a ++) { console.log(a); } console.log(''); //console.log(a); //报错 a不是全局变量 let 定义的a在块状作用域 console.log(''); let username = '小丽丽'; //全局作用域 function demo() { let age = 100; //局部作用域 } //所有的 结构语句 for while do while if switch 都有块状作用域 if (true) { let b = 1000; console.log(b) } //console.log(b) // 报错 b不是全局变量 let 定义的b在块状作用域 </script> </body> </html>
2. JS对象
2.1 构造函数和对象
构造就是类
function User([参数]) {
this.属性 = 值;
this.属性 = 值;
this.方法 = function(){
}
}
#实例一个对象
new 构造函数();
如果构造函数没有参数 可以 不加()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>类和对象</title> </head> <body> <h1>类(构造函数)和对象</h1> <hr> <script> //构造函数 就是 类 //定义一个 构造函数 跟函数 一模一样,this类似python中的self的作用 function User(name, age) { //声明对象的属性 this.userName = name; this.userAge = age; //声明一下对象 的方法 this.getInfo = function(){ console.log('姓名:'+this.userName+', 年龄:'+this.userAge+'<br>') } } //实例化对象----即new一个对象 var a = new User('小芳', 17); console.log(a); //使用对象的属性,直接对new出来的对象点属性名即可 console.log(a.userName); console.log(a.userAge); //调用对象的方法----直接对new出来的对象,点该对象下的方法名加括号即可调用该方法 a.getInfo(); //一个构造函数(类) 能够实例化成多个对象 var b = new User('小红', 18); b.getInfo(); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>构造函数</title> </head> <body> <h1>系统内置的构造函数</h1> <hr> <script> //一切皆对象 每个对象都有与之对应的构造函数 // 所有的对象 都有一个属性 .constructor (继承来的) function User() { } let u = new User(); console.log('对象u的构造函数: '+u.constructor); //function User() {} console.log('字符串对象的构造函数: ' + 'abc'.constructor); //function String() { [native code] } console.log('布尔值对象的构造函数: ' + true.constructor); //function Boolean() { [native code] } console.log('数字对象的构造函数: ' + (12).constructor); //function Number() { [native code] }数字类型默认后面也是有一个小数点的所以要加括号,也可以不加括号,使用两个点,如果不加括号只使用一个点就会报错 </script> </body> </html>
2.2 JS原型和原型链
原型
-
每个对象 都有原型 (原型仍然是一个对象)
-
对象可以继承原型的属性和方法
-
__proto__
所有对象都有该属性, 该属性指向该对象的原型
原型链
-
原型作为对象 也有原型
-
原型的原型的原型 就构成了 原型链
-
使用对象中某个属性的时候,先从对象中找,如果没有,从原型上找,原型如果也没有,继续向上找,知道顶层 (顶层的原型对象是一个 类型(类)(构造函数)是Object 的对象)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>原型</title> </head> <body> <h1>js原型</h1> <hr> <script> function User(){ this.name = '小丽丽'; } let u = new User(); console.log(u); console.log(u.__proto__); console.log(u.__proto__.__proto__); console.log(u.__proto__.__proto__.__proto__); console.log(u.name) console.log(u.toString); //来自原型 //再定义一个对象 Object是系统内置的构造函数 var a = new Object(); a.__proto__ = u; //将对象重新赋值给u这个对象,那么a这个原型就会继承u的属性 console.log(a) console.log(a.name) //小莉莉 /* User.prototype = 普通对象------等价于:u.__proto__ u.__proto__ */ //__proto__ 该属性 </script> </body> </html>
2.4 JS对象属性的调用
. 点
obj.name
obj.age
[] 中括号
obj['name']
obj['age']
obj['user-name']
任意的对象 都可以在对象实例化完成后, 添加属性和方法
2.4 Object 构造函数
js内建的构造方法 叫 Object
var obj = new Object()
josn方式定义对象
var obj = {属性:值, 属性:值} // new Object的简写
obj的构造含 是 Object
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Object</title> </head> <body> <script> //系统内建的构造函数 Object var o = new Object(); //先实例化一个o对象,在为其添加属性和方法 //创建好对象之后,再给对象添加属性和方法 o.name = '小丽丽'; o.age = 10; o.getInfo = function(){ console.log(this.name, this.age) } console.log(o) console.log(o.name) console.log(o.age) o.getInfo() var o1 = new Object(); //实例化出一个o1对象 //o1.__proto__ = o; //o1对象会继承o的属性和方法 console.log(o1); console.log(''); //实例化一个 Object类 的对象 简写----------将添加属性和方法写到一个大括号内,添加的属性是key:value的形式。但是一定要区分开来这是属性,不是Python中的字典 // python的key这里叫属性 声明对象的简写方式:var 对象名 = {属性1,属性2,方法1,方法2,} var data = {'name':'小丽丽', age:19, address:'上海', getInfo:function(){ console.log('getInfo'); }}; //python的字典----------方法也可以写在外面,添加的属性也可以写在外面 data.grade = '11'; console.log(data.constructor); console.log(data); console.log(data.name); data.getInfo(); //声明对象的时候 属性可以不加引号。 但是有些情况必须要加(如属性名有中划线) var content = { name: '小芳', age:100, 'user-name':'丽丽', //属性名有中划线就必须加引号,不加引号就会报错,因为中划线会被识别成减号 user_name:'大丽丽' //最后一个可以不加逗号 }; console.log(content); //调用属性---------通过点或中括号 console.log(content.name) //调用属性我们一般使用点,当然也可以使用下面的方法使用中括号 console.log(content.user_name) console.log(content['user-name']) //使用中括号就必须加引号 console.log(content['name']) //对象的所有的属性 都可以通过 [] 调用 var b = 123; console.log(b['constructor']) </script> </body> </html>
3. 实用技巧
3.1 从页面中获取元素
document.getElementById() 根据ID的值
document.getElementsByTagName() 根据标签名
document.getElmenntsByClassName() 根据class的值
document.getElementsByName() 根据name属性的值
document.querySelector(css选择器) 返回满足条件的第一个 元素对象
document.querySelectorAll(css选择器) 返回所有满足条件元素组成的 类数组对象
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>获取页面元素</title> </head> <body> <h1>获取页面元素</h1> <hr> <ul class="news-list"> <li><a href="#">Lorem ipsum dolor sit amet.</a></li> <li><a href="#">Lorem ipsum dolor sit amet.</a></li> <li><a href="#">Lorem ipsum dolor sit amet.</a></li> <li><a href="#">Lorem ipsum dolor sit amet.</a></li> <li><a href="#">Lorem ipsum dolor sit amet.</a></li> </ul> <div id="box"></div> <script> //使用js 获取页面中元素对象 var boxEle = document.querySelector('#box'); console.dir(boxEle); //console.dir()可以显示一个对象所有的属性和方法。 var li = document.querySelector('.news-list li'); console.log(li); //在控制台可以看到被修改的第一个li元素 li.innerHTML = '哈哈哈,我是第一个'; //修改获取到第一个元素的文本内容 //获取所有的li元素 返回一个类数组对象 类数组对象的每个成员才是元素对象 var lis = document.querySelectorAll('.news-list li'); //console.log(lis); //改变所有 li 元素的内的 内容 for (var i = 0; i < lis.length; i ++) { lis[i].innerHTML = '哈哈哈'+i; } </script> </body> </html>
3.2 给元素绑定事件
先获取元素
ele.onclick = function(){
}
获取元素的类数组对象, 遍历,挨个给每个元素绑定事件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>给元素绑定事件</title> <style> .list { list-style: none; padding: 0; margin: 0; width: 600px; } .list li { padding:10px; margin:5px 0px; border: 1px solid #ccc; } #btn { border:1px solid #ccc; padding:10px 20px; background: #f5f5f5; } </style> </head> <body> <h1>给元素绑定事件</h1> <hr> <button id="btn">点我</button> <ul class="list"> <li>Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> </ul> <script> //要给btn绑定元素----------也就是指向我们要修改的元素 var btn = document.querySelector('#btn'); //绑定事件 btn.onclick = function(){ this.innerHTML = '好疼'; //点击按钮时会见按钮二字改成好疼,松开按钮依然是修改后的结果 } //给每个 li元素都绑定事件 var lis = document.querySelectorAll('.list li'); //遍历,给每个元素绑定事件----------注意此时声明变量用的是let而不是var for (let i = 0; i < lis.length; i ++) { lis[i].onclick = function(){ //this表示 目前点的这个元素 this.innerHTML = '我被点了'; //点击列表中的文本内容,文本内容就会被修改成'我被点了',松开鼠标依然显示被修改后的结果 //lis[i].innerHTML = '我被点了'; //console.log(i) } } </script> </body> </html>
3.3 修改元素的CSS样式
ele.style.css属性名
ele.style.background
ele.style.border
ele.style.backgroundColor
ele.style['background-color']
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>给元素绑定事件</title> <style> .list { list-style: none; padding: 0; margin: 0; width: 600px; } .list li { padding:10px; margin:5px 0px; border: 1px solid #ccc; } #btn { border:1px solid #ccc; padding:10px 20px; background: #f5f5f5; } </style> </head> <body> <h1 >同志交友</h1> <hr> <button id="btn" style="padding:10px">点我</button> <ul class="list"> <li>Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> </ul> <script> //获取所有li的集合, var lis = document.querySelectorAll('.list li'); //返回所有满足条件元素组成的 类数组对象 //遍历 给每个li 绑定单击事件 for (var i = 0; i < lis.length; i ++) { lis[i].onclick = function(){ //this.style.border = '1px solid red'; //给元素绑定事件,这样这样当我们点击绑定的元素是就可以修改元素的样式 //this.style['border-color'] = 'red'; //也可以通过中括号修改css属性的值 this.style.borderColor = 'orange'; //所有带-的css属性 映射 为 小驼峰命名法(推荐使用这种方法,而不是中括号) this.style.background = '#ccc'; } } //获取元素的css 属性值 var btn = document.querySelector("#btn"); console.log(btn.style.padding) //pading的属性是为10px </script> </body> </html>
3.4 设置元素的class值
ele.className 可以赋值,也可以获取
ele.classList.add(‘值’) 添加一个class值
ele.classList.remove(‘值’) 删除一个class值
ele.classList.toggle(‘值’) 自动切换一个class值(有就删除,没有就添加)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>修改class的值</title> <style> .list { list-style: none; padding: 0; margin: 0; width: 600px; } .list li { padding:10px; margin:5px 0px; border: 1px solid #ccc; } .item { background: #ff6700; } .list li.active { border-color: red; background: pink; } </style> </head> <body> <h1 >同志交友</h1> <hr> <ul class="list"> <li>Lorem ipsum dolor sit amet.</li> <li class="item">Lorem ipsum dolor sit amet.</li> <li >Lorem ipsum dolor sit amet.</li> <li class="item">Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> <li class="item">Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> <li class="item">Lorem ipsum dolor sit amet.</li> </ul> <script> //获取所有li的集合 var lis = document.querySelectorAll('.list li'); //遍历 给每个li 绑定单击事件 for (var i = 0; i < lis.length; i ++) { lis[i].onclick = function(){ //this.className = 'active' //this.classList.add('active'); // remove() toggle() this.classList.toggle('active'); //如果class值里面没有 active 加上,有就删掉(toggle中文意思转换键)-----这样我们就可以设置 //console.log(this.classList) //判断 是否存在某个类的时候 使用 className } } </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>特效实例</title> <style> .list { list-style: none; padding: 0; margin: 0; width: 600px; } .list li { padding:10px; margin:5px 0px; border: 1px solid #ccc; } .list li.active { border-color: red; background: #ccc; } </style> </head> <body> <h1 >同志交友</h1> <hr> <ul class="list"> <li>Lorem ipsum dolor sit amet.</li> <li class="item">Lorem ipsum dolor sit amet.</li> <li >Lorem ipsum dolor sit amet.</li> <li class="item">Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> <li class="item">Lorem ipsum dolor sit amet.</li> <li>Lorem ipsum dolor sit amet.</li> <li class="item">Lorem ipsum dolor sit amet.</li> </ul> <script> //获取所有li的集合 var lis = document.querySelectorAll('.list li'); //遍历 给每个li 绑定单击事件 for (var i = 0; i < lis.length; i ++) { lis[i].onclick = function(){ //把所有的li都去掉class active for (var j = 0; j < lis.length; j ++) { lis[j].classList.remove('active'); } //把当前的添加上 this.classList.add('active') } } </script> </body> </html>
3.5 事件
onclick 单击
ondblclick 双击
oncontextmenu 右击
onmouseover/onmouseenter 鼠标悬浮到元素上
onmouseout/onmouseleave 鼠标离开元素
onmousemove 鼠标在上面移动
onmousedown 鼠标的按键按下
onmouseup 鼠标的按键抬起
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>鼠标事件</title> <style> #box { width: 400px; height: 300px; border: 2px solid orange; } </style> </head> <body> <div id="box"></div> <script> var boxEle = document.querySelector('#box'); boxEle.onmousedown = function(event) { console.log('啊,我被触发了', event.button); } boxEle.onmouseup = function(event) { console.log('啊,我松手了', event.button); } boxEle.onmousemove = function(event) { //获取鼠标在页面上的坐标 console.log('鼠标坐标:', event.clientX, event.clientY); } </script> </body> </html>
3.6 JS定时
单次定时
setTimeout(fn, delay) delay的单位是:毫秒
clearTimeout() 清除定时
多次定时
setInterval(fn, dealy) delay的单位是:毫秒
clearInterval() 清除定时
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>定时器</title> </head> <body> <h1>同志交友</h1> <script> //创建定时器 单次定时 setTimeout(function(){ document.body.style.background = '#f5f5f5'; }, 2000); // //多次定时 // setInterval(function(){ // //console.log('OK'); // var h1Ele = document.querySelector('h1'); // //随机颜色 // var r = Math.floor(Math.random() * 256); //0到255之间的随机数 // var g = Math.floor(Math.random() * 256); //0到255之间的随机数 // var b = Math.floor(Math.random() * 256); //0到255之间的随机数 // h1Ele.style.color = `rgb(${r}, ${g}, ${b})`; // }, 1000); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>定时案例</title> <style> h1 { margin-top:100px; text-align: center; font-size: 300px; } </style> </head> <body> <h1>10</h1> <script> var h1 = document.querySelector('h1'); var m = 10; var time = setInterval(function(){ h1.innerHTML = --m; //当m <= 0的时候 if (m <= 0) { clearInterval(time); //清除定时 h1.innerHTML = '你死定了' } }, 1000) </script> </body> </html>