当事件触发的时候会得到一个信息(事件对象),包含了跟事件相关的一些属性和方法的封装,只有事件在触发的时候才会得到
div.onclick = function(e){};其中e即为事件对象
获取事件对象兼容写法:e = e || event
事件 | 返回值 |
---|---|
e.buttons | 左键返回1,右键返回2,中键返回4 |
e.offsetX/offsetY | 获取事件触发最近的的盒子坐标 |
e.clientX/clientY | 获取浏览器边框的坐标 |
e.screenX/screenY | 获取显示屏坐标 |
e.pageX/pageY | 获取文档的坐标 |
<script>
var aDiv = [];
var cache = document.createDocumentFragment();
for(var i = 1; i <= 20; i++){
var div = document.createElement("div");
div.innerHTML = i;
aDiv.push(div);
cache.appendChild(div);
}
document.body.appendChild(cache);
//document绑定mousemove事件
document.onmousemove = function(e){
e = e || event;
var mouseX = e.clientX,
mouseY = e.clientY;
//从后往前,一次进一步
for(var i = aDiv.length-1; i > 0; i--){
aDiv[i].style.left = aDiv[i-1].style.left;
aDiv[i].style.top = aDiv[i-1].style.top;
}
//第0个赋值未当前鼠标坐标
aDiv[0].style.left = mouseX + "px";
aDiv[0].style.top = mouseY + "px";
}
</script>
keydown:按下键盘
keyup:弹起键盘
keypress:敲击键盘
键盘上每一个键都有一个唯一的编码,用来识别当前用户正在操作的是键盘上哪一个键
获取键码兼容写法:e.keyCode || e.which
特殊键码:e.altKey、e.ctrlKey、e.shiftKey用来判断是否按下alt ctrl和shift,返回值为布尔值
判断组合键:
if(e.keyCode==13&&e.altKey){
alert(‘同时按下了enter和alt’);
}
有一些html元素默认的行为,比如说a标签,点击后有跳转动作;form表单中的submit类型的input有一个默认提交跳转事件
阻止默认事件:return false;
兼容写法:
if(e.preventDefault){
e.preventDefault();
}else {
window.event.returnValue = false;//或者return false;
}
一个完整的事件:捕获阶段->目标阶段->冒泡阶段
由内向外,即子元素的事件被触发时,父级也会被触发
CSS样式:
#yeye{width: 400px;height: 400px;background: blue;}
#baba{width: 200px;height: 200px;background: red;}
#erzi{width: 100px;height: 100px;background: green;}
HTML代码:
<div id="yeye">
<div id="baba">
<div id="erzi"></div>
</div>
</div>
JS代码:
yeye.onclick = function(){
console.log("yeye");
}
baba.onclick = function(e){
console.log("baba");
//阻止冒泡
/*e.stopPropagation();
e.cancelBubble=true;//兼容IE*/
}
erzi.onclick = function(){
console.log("erzi");
}
阻止冒泡
e.stopPropagation();
e.cancelBubble = true;//兼容IE
DOM2级可以绑定多个事件
//兼容IE写法
if(window.attachEvent){
oDiv.attachEvent(“onclick”, function(){ … }); // IE只有冒泡阶段,所以没有第三个参数,而且需要加on;
}else{
oDiv.addEventListener( “click”, function(){ … },false); // false指冒泡阶段,true指捕获阶段
}
注冒泡阶段事件触发由内向外,捕获阶段事件触发由外向内
移除监听
//移除事件监听,第二个参数为必须,移除的事件处理函数
oDiv.removeEventListener( “click”,fn)
oDiv.detachEvent(“onclick”,fn)//兼容IE写法
事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以处理某一类型的所有事件。
使用场景主要用于事件源不确定的情况,可以把事件委托给父级(即将事件绑定在父级)
注只有事件发生在事件源才会执行
获取事件源:var target = e.target || e.srcElement
判断是否在事件源上:target.nodeName === “标签名”
CSS样式:
ul{border: 3px solid #666;width: 250px;}
li{width: 200px;height: 50px;background: red;margin: 30px 0;}
HTML代码:
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
</ul>
<button>按钮</button>
JS代码:
var ul = document.querySelector("ul");
//事件委托
ul.onclick = function(e){
e = e || event;
//获取事件源
var target = e.srcElement || e.target;
if(target.nodeName === "LI")
console.log(target.innerHTML);
//this
}
document.querySelector("button").onclick = function(){
var li = document.createElement("li");
li.innerHTML = "wgrf";
ul.appendChild(li);
}
写法一:
var reg = new RegExp(“字符”);
var str = “字符串”;
reg.test(str);//返回bool值代表是否匹配成功
写法二:
var reg = /字符/;
var str = “字符串”;
reg.test(str);
[]:匹配其中的某一个字符
[a-z]匹配所有小写字母
[0-9]匹配任意一个数字(或 \d)
():分组,将小括号里面的内容作为整体进行匹配
/(ab)|(cd)/匹配"ab"或者"cd"
/(a|b)cd/匹配"acd"或者"bcd"
注小括号、竖线不要放在[]内,这样无意义
^:
在中括号中表示非:/[^a-z]/不能出现小写字母
不在中括号中表示匹配开头:/^[a-z]/必须以小写字母开头
$:匹配结尾
/^ $/表示完整匹配
转义字符:元字符
\d —— [0-9] 数字
\w —— [a-z0-9_A-Z] 数字,字母,下划线
\s —— 空白字符
\D —— 非数字
\W —— 非数字,字母,下划线
\S —— 非空白字符
. —— 全部字符
\b —— 匹配单词边界
\B —— 匹配非单词边界
\0 —— 匹配null字符
\n —— 匹配换行符
\f —— 匹配换页符
\r —— 匹配回车符
\t —— 匹配制表符
\v —— 匹配垂直制表符
在线 Unicode编码转换: http://tool.chinaz.com/tools/unicode.aspx
量词(单位名称)
{n} —— 匹配n次
{n,m} —— 匹配最少n次,最多m次
QQ号验证 /^[1-9]\d{4,10}$/
{n,} —— 最少n次,最多不限
+ —— {1,}
? —— {0,1}可有可无,最多一个
* —— {0,}可有可无,个数不限
正则参数
正则对象中有一个参数,可以传入对应的值实现不同功能
i:忽略大小写
var re = new RegExp(“a”,“i”)
或var re = /a/i
g:全局查找
reg = /\d+/ g
m: 多行查找(必须与g一起实用,并且,当使用^和$模式时才会起作用)
正则对象的方法
test方法:
该方法用来测试某个字符串是否与正则匹配,匹配就返回true,否则返回false
compile方法:
该方法的作用是能够对正则表达式进行编译,被编译过的正则在使用的时候效率会更高,适合于对一个正则多次调用的情况下,如果对一个正则只使用一两次,那么该方法没有特别显著的效应
exec方法:
返回的是一个数组,数组元素为匹配的子字符串
优点
1.全局变量声明时必须加var
2.this无法指向全局对象
3.函数内重名属性
4.arguments对象
4.1.arguments对象不允许被动态改变;
4.2.arguments对象不允许被自调用;
5.新增保留字(即关键字)
字符串
trim();// 去掉字符串前后空格
trimLeft();//去掉左边的空格
trimRIght();//去掉右边的空格
JSON
JSON.parse(str);//json序列化,将符合json格式的字符串转换为json
JSON.stringify();//json转换为字符串
var data = [
{"name": "zhangsan", "age":18},
{"name": "zhangsan", "age":18},
{"name": "zhangsan", "age":18},
{"name": "zhangsan", "age":18},
]
var str = JSON.stringify(data);
console.log(str);
var data2 = JSON.parse('[{"name":"zhangsan","age":18},{"name":"zhangsan","age":18},{"name":"zhangsan","age":18},{"name":"zhangsan","age":18}]');
console.log(data2);
var data1 = {
"likes": ["like1","like2","like2","like2"],
"go":{"key":"value"}
}
console.log(data1);
Object
Object.defineProperty(obj,prop,descriptor);//在一个对象上定义一个新属性,或者修改一个对象的现有属性, 返回这个对象
参数说明:obj目标对象,prop需定义或修改的属性的名字,descriptor目标属性所拥有的特性。
数据属性:
var obj = new Object();
Object.defineProperty(obj, ‘name’, {
configurable: false,
writable: true,
enumerable: true,
value: ‘张三’
})
console.log(obj.name) //张三
Object.getOwnPropertyDescriptor(obj,prop);//返回prop的属性描述符
Object.defineProperties(obj, props); //在一个对象上定义一个或多个新的属性或修改现有属性,返回这个对象
var obj = new Object();
Object.defineProperties(obj, {
name: {
value: ‘张三’,
configurable: false,
writable: true,
enumerable: true
},
age: {
value: 18,
configurable: true
}
})
console.log(obj.name, obj.age) // 张三, 18
Object.keys(obj);//获取obj的所有属性名称,如果属性名为数字还会自动排序,返回数组
Object.values(obj);//获取obj的所有属性值,返回数组
Object.assign(对象1,对象2,…);//合并多个对象,相同属性名后面的会生效
const object1 = {
a: 1,
b: 2,
c: 3
};
const object2 = Object.assign({c: 4, d: 5}, object1);
console.log(object2);//{c:3, d:5, a:1, b:2}
块级作用域一种普遍存在于各个语言中的作用域范围,一个大括号就是一个块级作用域
let声明变量
在块级作用域中用let定义的变量只在块中生效
例1
{
var a = 10;
let b = 20;
}
console.log(a)//10
console.log(b)// a is not defined
例2
for(let i = 0 ; i < aLi.length ; i ++){
aLi[i].onclick = function(){
console.log(i);// 对应下标
}
}
用var定义i的方式所有的i++都执行在同一个i上,故触发事件时i始终是aLi.length;用let定义的i每次循环都是一个新的块,各个i的值互不干扰
let声明的变量不会提升
console.log(a); //undefined;
var a = 10;
console.log(b)//b is not defined;
let b = 10;
暂时性死区
var a = 10;
if(true){
console.log(a);//ReferenceError(引用错误): a is not defined;
let a = 20;
}
ES6规定在某个区块中, 一旦用let或const声明一个变量,那么这个区块就变成块级作用域,用let 或者const声明的变量即为该区块绑定, 该变量不受任何变量影响。 在该变量使用let声明前不可以用。
const声明常量
用const声明的常量不可修改值,定义的数组不允许被直接修改,但可以对值进行操作
const arr = [5,6];
for(let i = 0;i < arr.length;i++){
arr[i] = i;
}
arr.push(4,5);
console.log(arr);//0,1,4,5
…扩展运算符把数组或类数组对象展开成一系列用逗号隔开的值
var foo = function(a, b, c) {
console.log(a);
console.log(b);
console.log( c);
}
var arr = [1, 2, 3];
//传统写法
//foo(arr[0], arr[1], arr[2]);
//使用扩展运算符
foo(...arr);
…rest运算符把逗号隔开的值序列组合成一个数组
var bar = function(a, ...args) {
console.log(a);
console.log(args);
}
bar(1, 2, 3, 4);
重复字符串
‘x’.repeat(3) //xxx;
判定字符串中是否存在某个字符串返回true或false
includes(searchvalue[,start]) :从start位开始的字符串中是否包含searchvalue,默认为0位
startsWith(searchvalue[,start]):从start位开始在字符串中匹配searchvalue,默认为0位
endsWith(searchvalue[,end]):end位之前匹配searchvalue,默认为最后一位
let str = "hello world";
console.log(str.includes("world"));
console.log(str.endsWith("o ", 6));
console.log(str.startsWith("w", 6));
for of遍历字符串
var s = "abc";
for(let b of s){
console.log(b) // "a" "b" "c"
}
模板字符串
1.用` `括起来的字符串可以实现强大的功能
传统拼接带有标签的字符串:
bianliang + “这是一个文字” + obj.name + " " + bianliang
用拼接带有标签的字符串:
` ${bianliang} 这是一个文字${obj.name}${bianliang} `
注 在` `中\n可以实现换行
console.log( `In JavaScript \n is a line-feed.`);
//console.log(`string text line 1
string text line 2`);
2.用${ }括住变量让拼接变得非常容易
注`${}`还可以调用函数
var obj = {
name:"张三",
age:18
}
var str = ''+
'姓名:'
+ obj.name +''+
'年龄:'
+ obj.age +''+
'';
function foo(){
return "一句话";
}
var str = `
姓名:${obj.name}
年龄:${obj.age}
${obj.age >= 18? "可以上网了":"回家写作业"}
${foo()}
`;
document.body.innerHTML = str;
标准格式
var 函数名 = (形参) => {
函数体;
}
优点
1.因为箭头函数没有自己的this,可以自动绑定外层的this,但因此也无法做构造函数
document.querySelector(“button”).onclick = function(){
setTimeout(() => {
console.log(this);//这里的this为button
},1000);
}
2.简洁,书写量少
缺点
1.箭头函数是不能new的,它的设计初衷就跟构造函数不太一样
2.箭头函数如果要返回一个JSON对象,必须用小括号包起来 var foo = ()=>({id:3})
3.对代码的可读性伤害大
var arr = [2,43,5,30];
var [a,b,c,d=0] = arr;
console.log(a,b,c,d);//2 43 5 30
var obj = {name:"lisi", age:80, gender: "female"};
var {age, name, gender="male"} = obj;//解构对象,可以根据属性名取到属性值
console.log(age, name, gender); //80 "lisi" "female"
var json = [
{name:"lisi", age:80, gender: "female"},
{name:"liwu", age:70, gender: "male"},
{name:"liliu", age:60, gender: "female"}
]
var [a,{name},c] = json;//a为json中的第一个对象,以此类推,{name}为第二个对象的name属性
console.log(name);
Symbol函数会生成一个唯一的值可以理解为Symbol类型跟字符串是接近的 但每次生成唯一的值,也就是每次都不相等,至于它等于多少,并不重要 这对于一些字典变量,比较有用
var s1 = Symbol();
var s2 = Symbol();
var s3 = Symbol(“abc”);
var s4 = Symbol(“abc”);
s1不等于s2
s3不等于s4
适用于只需要关心状态(属于哪个状态),但是不用知道内部结构(不关心值为多少)的情况
变色案例:
<div style="width: 200px;height: 200px;background: red;"></div>
<script>
var obj ={
red: Symbol(),
blue: Symbol(),
green: Symbol(),
yellow: Symbol()
}
var color = obj.red;
document.querySelector("div").onclick = function(){
if(color === obj.red){
this.style.background = "blue";
color = obj.blue;
}else if(color === obj.blue){
this.style.background = "green";
color = obj.green;
}else if(color === obj.green){
this.style.background = "yellow";
color = obj.yellow;
}else if(color === obj.yellow){
this.style.background = "red";
color = obj.red;
}
}
</script>
没有重复元素的集合
let imgs = new Set();
imgs.add(1);
imgs.add(1);
imgs.add(5);
imgs.add(“5”);
imgs.add(new String(“abc”));
imgs.add(new String(“abc”));
console.log(imgs) ;
// 打印的结果: 1 5 ‘5’ ‘abc’ ‘abc’
注因为对象是引用类型,所以两个String虽然值相同但各自的地址不同,不算重复元素
遍历Set
数组去重巧妙写法
var newarr = […new Set(array)];
一种集合,即映射
set设值get取值
let map = new Map();
map.set(“S230”, “张三”);
map.set(“S231”, “李四”);
map.set(“S232”, “王五”);
获取某一个元素 map.get(“s232”); //王五
遍历Map
for(let [key,value] of map){
console.log(key,value); //循环遍历,配合解构赋值
}
tools封装函数
/* 让元素匀速运动
* obj DOMObj 运动的DOM元素
* attr string 运动的属性
* end number 终点值
* duration number 运动时间
*/
move: function(obj, attr, end, duration){
//每次进来之前先把上一次的定时器清除
clearInterval(obj.timer);
//起始值
var start = parseInt(this.getStyle(obj, attr));
//总距离
var distance = end - start;
//总步数
var steps = Math.floor(duration / 30);
//速度(每一步要走的距离)
var speed = distance / steps;
//timer要唯一,写在对象属性上
obj.timer = setInterval(function(){
//往前走一步
start += speed;
if(Math.abs(end - start) <= Math.abs(speed)){
start = end;
clearInterval(obj.timer);
}
obj.style[attr] = start + "px";
},30);
}
元素运动
JavaScript写法
//html&cs
<body>
<button onclick="fn()">运动</button>
<div></div>
<script src="../tools.js"></script>
<script>
var div = document.querySelector("div");
//var timer = null;
function fn(){
tools.move(div, "left", 500, 2000);
}
</script>
</body>
JavaScript+CSS
//CSS:
div{
width:100px;
height: 100px;
background: red;
position: absolute;
left: 0;
}
.move{
transition: all 2s linear;
left: calc(100% - 100px);
}
//html&js
<div></div>
<script type="text/javascript">
var div = document.querySelector("div");
div.onclick = function(){
div.className = "move";
}
</script>
列表悬停和点击样式
//CSS样式
<style>
*{margin: 0; padding: 0;}
ul {list-style:none;}
body {
background-color: #000;
}
.nav {
width: 800px;
height: 42px;
background:url(rss.png) no-repeat right center #fff;
margin: 100px auto;
border-radius: 5px;
position: relative;
}
.cloud {
width: 83px;
height: 42px;
position: absolute;
top: 0;
left: 0;
background: red;
opacity: .5;
}
.nav ul {
position: absolute;
top: 0;
left: 0;
}
.nav li {
float: left;
width: 88px;
height: 42px;
line-height: 42px;
text-align: center;
color: #000;
cursor: pointer;
}
</style>
//html
<div class="nav" id="nav">
<span class="cloud" id="cloud"></span>
<ul id="box">
<li>首页新闻</li>
<li>千锋师资</li>
<li>千锋活动策划</li>
<li>企业文化</li>
<li>招聘信息</li>
<li>公司简介</li>
<li>上海校区</li>
<li>广州校区</li>
</ul>
</div>
//js
<script src="../tools.js"></script>
<script>
var aLi = document.querySelector("#box").children;
var cloud = document.querySelector("#cloud");
var left = 0;
aLi = Array.from(aLi);
aLi.forEach(function(li){
//console.log(li);
tools.on(li, "mouseover", function(){
//console.log(cloud, this.offsetLeft);
tools.move(cloud, "left", this.offsetLeft, 500);
})
tools.on(li, "mouseout", function(){
tools.move(cloud, "left", left, 500);
})
tools.on(li, "click", function(){
//记录当前位置
left = this.offsetLeft;
})
});
</script>