JavaScript学习之路第三周

目录

  • day11
      • 事件
          • 鼠标事件
          • 键盘事件
      • 默认行为
  • day12
      • 冒泡阶段
      • 事件监听
      • 事件委托
  • day13
      • 正则表达式
  • day14
      • ES5严格模式
          • 严格模式行为变更
      • ES5新增常见方法
      • ES6
          • let/const
          • 扩展运算符和rest运算符
          • 字符串新增方法
      • 箭头函数
      • 解构赋值
      • symbol
      • Set和Map结构
          • Set
          • Map
  • day15
      • JavaScript结合css实例

day11

事件

当事件触发的时候会得到一个信息(事件对象),包含了跟事件相关的一些属性和方法的封装,只有事件在触发的时候才会得到

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;
}

day12

一个完整的事件:捕获阶段->目标阶段->冒泡阶段

冒泡阶段

由内向外,即子元素的事件被触发时,父级也会被触发

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);
}

day13

正则表达式

写法一
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方法:
返回的是一个数组,数组元素为匹配的子字符串

day14

ES5严格模式

优点

  • 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
  • 消除代码运行的一些不安全之处,保证代码运行的安全;
  • 提高编译器效率,增加运行速度;
  • 为未来新版本的Javascript做好铺垫。
    use strict进入严格模式
严格模式行为变更

1.全局变量声明时必须加var

2.this无法指向全局对象

3.函数内重名属性

4.arguments对象
4.1.arguments对象不允许被动态改变;

4.2.arguments对象不允许被自调用;

5.新增保留字(即关键字)

  • implements,
  • interface,
  • let,
  • package,
  • private,
  • protected,
  • public,
  • static,
  • yield

ES5新增常见方法

字符串
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目标属性所拥有的特性。
数据属性

  • configurable:表示能否通过delete删除此属性,默认为false(不能)
  • enumerable:表示该属性是否可枚举,即通过for-in或Object.keys()返回属性,默认为false
  • value:该属性对应的值,默认为undefined
  • writable:能否修改属性的值,默认为false

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}

ES6

let/const

块级作用域一种普遍存在于各个语言中的作用域范围,一个大括号就是一个块级作用域

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
扩展运算符和rest运算符

…扩展运算符把数组或类数组对象展开成一系列用逗号隔开的值

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 函数名 = (形参) => {
函数体;
}

  • 如果箭头函数只有一个形参,那么可以省略小括号
    var foo = str => {
    console.log(str);
    }
  • 如果函数体只有一句话,那么可以省略大括号
    var foo = str => console.log(str);
  • 如果只有一句话,并且这句话就是return,可以省略return关键字
    var foo = str => str+“abc”;

优点
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函数会生成一个唯一的值可以理解为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>

Set和Map结构

Set

没有重复元素的集合

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

  • 根据KEY遍历
    for(let item of imgs.key()){
    console.log(item);
    }//1 //5 //“5” //String{“abc”} //String{“abc”}
  • 根据VALUE遍历
    for(let item of imgs.values()){
    console.log(item);
    }//1 //5 //“5” //String{“abc”} //String{“abc”}
  • 根据KEY-VALUE遍历
    for(let item of imgs.entries()){
    console.log(item);
    }//[1,1] //[5,5] //[“5”,“5”] //[String,String] //[String,String]
    因为元素不允许重复的特性,Set中的key=value,因此也无法通过下标方式访问

数组去重巧妙写法
var newarr = […new Set(array)];

Map

一种集合,即映射
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); //循环遍历,配合解构赋值
}

day15

JavaScript结合css实例

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>

你可能感兴趣的:(JavaScript学习之路第三周)