基础
var 、let、const关键字
数据类型
值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。
引用数据类型:对象(Object)、数组(Array)、函数(Function)。
-
注:Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值。
-
JavaScript 拥有动态类型。这意味着相同的变量可用作不同的类型
-
对象由花括号分隔。在括号内部,对象的属性以名称和值对的形式 (name : value) 来定义。属性由逗号分隔:
var person={firstname:"John", lastname:"Doe", id:5566};
上面例子中的对象 (person) 有三个属性:firstname、lastname 以及 id。
数组
1、数组的两个方法形成栈结构
- push:
- 格式:数组.push(参数1、参数2。。。)
- 功能:给数组的末尾添加元素
- 返回值:插完元素以后数组的长度。
- pop:
- 格式:数组.pop()
- 返回值:取出一个元素
- 功能:从数组末尾取下一个元素
2、队列结构
- shift():
- 格式:数组.shift()
- 功能:从数组的头部取下一个元素
- unshift():
- 格式:数组.unshift(参数1、参数2、。。。)
- 功能:从数组头部插入元素
3、concat()
- 拷贝原数组,生成新数组
- 合并数组
- 格式:数组.concat(数组,数组,。。)
- 返回值,合成新的数组,原数组不会改变
- 就算传入的是数组,数组中的元素要单独拆出来再进行合并
4、slice()
- 格式:数组.slice(start,end);
- 功能:可以基于当前数组获取指定区域元素[start,end],提取出元素生成新的数组
- 返回值:生成新的数组,原数组不会改变
5、splice()
- 格式:数组.splice(start,end,数据1,数据2,。。);
- 参数:
- start 开始截取的位置
- length:截取的元素的长度
- 第三个参数开始,在start位置,插入的元素
- 返回值:截取下来的元素组成的数组
6、join()
- 格式:数组.join(字符串)
- 功能:将数组中的元素,用传入的拼接符,拼接成一个新的字符串
7、reverse():逆序
8、sort():数组排序。默认是从小到大排序,按照字符串排序
- 参数:一个函数,代表要怎么去进行排序(固定用法)
9、concat(),将原数组复制一份,然后赋值给另一个变量时,另外一个变量更改元素,不会影响原数组。这就是引用类型的变量;
10、声明提升
在当前作用域,声明变量和函数,会直接提升在整个代码的最前面
11、省略var声明变量,会被js强制声明为全局变量
12、严格模式:
- 写在哪个作用域下,哪个作用域就会生效
- 使用
“use strict”
声明 - 注意:尽量不要将严格模式声明在全局位置
使用严格模式后行为变更
- 全局变量声明时,必须加var
- this无法指向全局对象
- 函数内重名属性
- arguments对象不允许被动态改变
//没加严格模式之前
function f(n1, n2) {
n1 = "hello";
console.log(arguments[0] + "," + arguments[1]); //输出hello,2
}
f(1, 2);
//加严格模式
function f(n1, n2) {
"use strict"
n1 = "hello";
console.log(arguments[0] + "," + arguments[1]); //输出1,2
}
- 新增保留字:implements,interface,let,package,private,protected,public,static,yield,不可能将这些声明成变量。
严格模式的目的:
1、消除js语法的一些不合理,不严谨之处,减少一些怪异行为;
2、消除代码运行的一些不安全之处,保证代码运行的安全。
3、提高编译器效率,增加运行速度
4、为未来新版本的js做铺垫
注:“严格模式”体现了js更合理、更安全、更严谨的发展方向,包括ie10在内的主流浏览器,都支持它。
13、indexOf(item,start):在数组中查找第一次出现item元素的下标,从start开始查
14、map:将数组中的元素进行特定的操作,并返回新的数组,原数组不变
15、filter():过滤
var arr = [1,2,3];
var newArr = arr.filter(function(item,index,arr){
return item > 2;
})
console.log(newArr); // 3
console.log(arr); // 1,2,3
16、some():判断数组里面有不有符合条件的,用法与filter一样
17、every():判断数组里面所有元素是否符合条件,用法与上面一样
18、reduce():
字符串
1、字符串声明
- 通过new运算符
- 省略new
- 字符串常量赋值
2、访问单个字符:charAt(下标,从0开始)
注意:字符串是只读,不可变的,既是基本数据类型又是对象类型
3、typeof:判断指定变量是什么类型的
4、charCodeAt():访问字符串对应下标下的ASCII码值
5、fromCharCode()将传入的 ASCII码转成字符
。。。。
详情
BOM对象(browser object model)
1、confirm():弹出一个对话话,点确定返回ture,取消返回false
2、alert()
3、prompt():弹出一带输入框的提示框
- 第一个参数:面板显示的内容
- 第二个参数:输入框里面的默认(可以不传入)
4、open()
- 参数1:跳转的URL,打开一个新窗口,并加载该url
- 参数2:字符串,给打开的窗口起一个名字
5、history对象
- 管理的是当前窗口的历史记录(只要加载了不同的url就会产生一条历史记录)
- history.lenth:获取历史记录条数
- history.back():返回上一条历史记录
- history.forward():返回下一条历史记录
- history.go():
- 参数:0 :刷新当前页面
- 正整数: 前进n条记录
- 负整数:后退n条记录
6、location(地址栏)的属性
URL:统一资源定位符
协议://ip(域名)/:端口号/路径/?查询字符串#锚点
- 协议:location.protocol
- 主机名:location.hostname
- 端口号:location.prot
- 路径:location.pathname
- 查询字符串:location.search
- 锚点:# location.hash
方法:
location.assign(url),在当前窗口跳转到这个url
location.replace(rul),在当前窗口替换成新的url,不会产生历史记录
location.reload(),刷新当前窗口,传入ture,不经过浏览器缓存强制从服务器加载
DOM 和DOM下节点获取
节点类型:
- 元素节点:“div”
- 属性节点:“id = ‘div’”
- 文本节点:div文本
获取元素节点的方法:
-
document.getElementById(id):通过id获取到节点对象
设置行间属性的值:.id,.title,.className
设置样式:.style.width,.style.height 。。。(只能访问标签行间的样式) -
document.querySelector():
querySelector() 方法返回文档中匹配指定 CSS 选择器的一个元素。
注意: querySelector() 方法仅仅返回匹配指定选择器的第一个元素。如果你需要返回所有的元素,请使用 querySelectorAll() 方法替代。 -
document.querySelectorAll:
querySelectorAll() 方法返回文档中匹配指定 CSS 选择器的所有元素,返回 NodeList 对象。
NodeList 对象表示节点的集合。可以通过索引访问,索引值从 0 开始。
提示: 你可以使用 NodeList 对象的 length 属性来获取匹配选择器的元素属性,然后你可以遍历所有元素,从而获取你想要的信息。
获取当前有效元素:
/**
* 根据传入的结点对象和样式,分别对浏览器兼容进行判断后,选择对应的兼容方法
* currentStyle[]对象:返回所有样式声明包括外部、内部、内联,按照css层叠规则作用于元素的最终样式
* getComputedStyle(node)[cssStyle]:可以获取当前元素所使用的css属性值。
* @param {需要获取有效样式的结点对象} node
* @param {要获取的样式属性名} cssStyle
*/
function getStyle(node, cssStyle) {
return node.currentStyle //踩坑点:没有()
? node.currentStyle[cssStyle]
: getComputedStyle(node)[cssStyle];
}
练习:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>定时器</title>
<style>
#div1 {
width: 400px;
height: 200px;
background-color: white;
border: 1px solid black;
margin: 100px auto;
text-align: center;
line-height: 200px;
font-size: 18px;
}
</style>
<script>
/*写一个定时器,每个一秒修改一次div内文本颜色和文字大小,最开始这个文字是默认大小,大小开始增大,当增大了6次以后,
文字大小开始缩小,缩小6次,文字再开始增大。*/
//定义一个方法,生成随机的颜色范围:0-255
function randomRgba() {
/* let r = parseInt(Math.random()*256); //random生成0.1-0.9之间的随机数,不是整数,所以需要强制类型转换,后面乘n就是生成0-n-1之间的数
console.log(r); */
let str =
"rgba(" +
parseInt(Math.random() * 256) +
"," +
parseInt(Math.random() * 256) +
"," +
parseInt(Math.random() * 256) +
"," +
1 +
")";
return str;
}
onload = function () {
let node = document.getElementById("div1");
let speed = 5;//每次增大的范围
let count = 0; //计数
setInterval(() => {
node.style.color = randomRgba();
//获取字体大小
let size = parseInt(getStyle(node,"font-size"));
//将字体逐渐放大
node.style.fontSize = (size+speed)+"px"
count ++;
if(count % 6 == 0) {
speed *= -1;
}
}, 1000);
};
/**
* 根据传入的结点对象和样式,分别对浏览器兼容进行判断后,选择对应的兼容方法
* currentStyle[]对象:返回所有样式声明包括外部、内部、内联,按照css层叠规则作用于元素的最终样式
* getComputedStyle(node)[cssStyle]:可以获取当前元素所使用的css属性值。
* @param {需要获取有效样式的结点对象} node
* @param {要获取的样式属性名} cssStyle
*/
function getStyle(node, cssStyle) {
return node.currentStyle //踩坑点:没有()
? node.currentStyle[cssStyle]
: getComputedStyle(node)[cssStyle];
}
</script>
</head>
<body>
<div id="div1">hello</div>
</body>
</html>
DOM进阶
1、setAttribute
2、getAttribute
3、removeAttribute
- class属性的访问
- 支持自定义属性的访问
4、innerHTML:获取标签之间的内容,可以赋值,会解析HTML标签
5、innerText:获取标签之间的纯文本,可以赋值
6、outerHTML:从外标签开始到外标签结束
7、childNodes:访问当前节点下所有的子节点
8、firstChild:访问子节点中的首位
9、lastChild:访问子节点中的最后一位
10、nextSibling:访问当前节点兄弟节点中的下一个节点
11、previousSibling:访问当前节点兄弟节点中的上一个节点
下面这些方法IE8一下不兼容
12、节点操作
- document.write():覆盖页面上原有的内容
- createElement():创建一个节点
- node1.appendChild(node2):将node2节点插入到node1节点的子节点的末尾
- document.createTextNode(文本):创建文本节点
- node1.parentNode.insertBefore(node2,node1):将node2添加到node1前面
- node1.parentNode.replaceChild(node2,node1):用node2节点将node1节点替换
- node.cloneNode():克隆出来新节点(传入true,克隆节点本身和子节点)
节点操作案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>节点操作</title>
<style>
#div1 {
background-color: orange;
width: 300px;
height: 70px;
}
#i1 {
width: 290px;
height: 30px;
margin-left: 1px;
}
.b {
margin-top: 5px;
margin-left: 40px;
color: white;
background-color: black;
}
#div2 {
width: 300px;
height: 600px;
background-color: rgba(255, 238, 0, 0.377);
}
</style>
<script>
//定义一个方法,生成随机的颜色范围:0-255
function randomRgba() {
let str =
"rgba(" +
parseInt(Math.random() * 256) +
"," +
parseInt(Math.random() * 256) +
"," +
parseInt(Math.random() * 256) +
"," +
1 +
")";
return str;
}
window.onload = function () {
//获取div1节点
let div1 = document.getElementById("div1");
//获取输入框
let input = document.getElementById("i1");
//获取所有的按钮
let buttons = document.getElementsByClassName("b");
//获取div2
let div2 = document.getElementById("div2");
//设置第一个按钮的操作
buttons[0].onclick = function () {
//创建一个元素节点div
let newdiv = document.createElement("div");
//创建一个文本节点,并将输入框的值添加到文本节点
let text = document.createTextNode(input.value);
//将文本节点添加到div节点下
newdiv.appendChild(text);
//将新div添加颜色样式
newdiv.style.backgroundColor = randomRgba();
//将新的div添加到div2节点的末尾
div2.appendChild(newdiv);
//添加完将输入框清空
input.value = "";
//创建一个按钮节点
let b = document.createElement("button");
b.innerText = "删除";
b.style.marginLeft = "10px";
b.onclick = function () {
div2.removeChild(newdiv);
};
newdiv.appendChild(b);
};
//设置第二个按钮的操作
buttons[1].onclick = function () {
//删除最后一个节点
div2.removeChild(div2.lastChild);
};
//克隆最后一个节点
buttons[2].onclick = function () {
let divlast = div2.lastChild.cloneNode(true);
div2.appendChild(divlast);
};
};
</script>
</head>
<body>
<div id="div1">
<input type="text" id="i1" />
<button type="button" class="b">添加</button>
<button type="button" class="b">删除</button>
<button type="button" class="b">复制</button>
</div>
<div id="div2"></div>
</body>
</html>
选项卡案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>选项卡操作</title>
<style>
#div1 {
width: 300px;
height: 330px;
background-color: antiquewhite;
}
#div1 .activity {
background-color: orange;
color: blue;
}
#div1 div {
width: 295px;
height: 300px;
border: 1px solid black;
display: none;
}
</style>
<script>
onload = function () {
//获取div1
let div1 = document.getElementById("div1");
//获取div1下所有的按钮和div
let buttons = div1.getElementsByTagName("button");
let divs = div1.getElementsByTagName("div");
let index = 0;
for (let i = 0; i < buttons.length; i++) {
buttons[i].onclick = function () {
for (let j = 0; j < buttons.length; j++) {
buttons[j].className = "";
divs[j].style.display = "none";
}
this.className = "activity";
divs[i].style.display = "block";
};
}
};
</script>
</head>
<body>
<div id="div1">
<button class="activity">JavaScript</button>
<button>Java</button>
<button>Python</button>
<div style="display: block">
JavaScript是世界上最流行的脚本语言,因为你在电脑、手机、平板上浏览的所有的网页,以及无数基于HTML5的手机App,交互逻辑都是由JavaScript驱动的。
简单地说,JavaScript是一种运行在浏览器中的解释型的编程语言。
</div>
<div>
JavaScript一度被认为是一种玩具编程语言,它有很多缺陷,所以不被大多数后端开发人员所重视。很多人认为,写JavaScript代码很简单,并且JavaScript只是为了在网页上添加一点交互和动画效果。
</div>
<div>
但这是完全错误的理解。JavaScript确实很容易上手,但其精髓却不为大多数开发人员所熟知。编写高质量的JavaScript代码更是难上加难。
</div>
</div>
</body>
</html>
offset系列方法
- offsetWidth:能获取元素宽并且以数字返回(width+border+padding,眼睛能看到的实际的宽都算上)
- offsetHeight:类似offsetWidth
- offsetLeft/top:眼睛能看到实际距离第一个有定位的父节点的距离
文档碎片
<script>
onload = function () {
let div1 = document.getElementById("div1");
/* console.time("test1"); //计时开始
for (let i = 0; i < 100000; i++) {
let newdiv = document.createElement("div");
div1.appendChild(newdiv);
}
console.timeEnd("test1"); //计时结束test1: 112.801025390625 ms */
//使用文档碎片方式:现将全部的节点创建出来,添加到一个节点里面,然后在插入div
console.time("test1");
let node = document.createElement("div");
for (let i = 0; i < 100000; i++) {
let newdiv = document.createElement("div");
node.appendChild(newdiv);
}
div1.appendChild(node);
console.timeEnd("test1");//test1: 84.226806640625 ms
};
</script>
数组和对象遍历方法JS数组遍历的十二种方式
- 数组
1、for循环
for (let index = 0; index < array.length; index++) {
const element = array[index];
}
2、for…in快速遍历
for (const key in object) {
if (object.hasOwnProperty(key)) {
const element = object[key];
}
}
3、foreach
array.forEach(element => {
});
4、for…of
for (const iterator of object) {
}
javascript原生遍历方法的建议用法:
用for循环遍历数组
用for-in遍历对象
用for-of遍历类数组对象(ES6)
用Object.keys()获取对象属性名的集合
事件
事件是发生并得到处理的
绑定事件:1、内联模式 2、外联模式(脚本模式)
绑定事件格式:
元素节点.on + 事件类型 = 匿名函数
click 事件类型 onclick:事件处理的函数
事件的种类
1、鼠标事件
- click 单击
- dblclick 双击
- mouseover 鼠标移入(经过子节点也会触发)
- mouseout 鼠标移出(经过子节点会触发)
- mousemove 鼠标移动(会不停的触发)
- mouseenter 鼠标移入(经过子节点不会触发)
- mouseleave 鼠标移出 (经过子节点不会触发)
2、键盘事件(表单元素,全局Window)
- keydown 键盘按下(如果按下不松手,会一直触发)
- keyup 键盘抬起
- keypress 键盘按下(只支持字符键)
3、HTML事件
window事件
- load :当页面加载完以后会触发
- unload:当页面解构的时候触发(刷新页面,关闭当前页面)只有IE兼容
- scroll:页面滚动触发
- resize:页面窗口大小发生变化
表单事件
- blur:失去焦点
- focus:获取焦点
- select:选中文本时触发
- change:文本进行修改并失去焦点重复
- submit:但我们点击submit上的按钮才触发
- reset
事件绑定:
- 系统会在事件触发的时候,生成一个事件对象
- 触发事件的时候,系统会自动去调用事件绑定的函数
- 获取事件对象固定写法:var e = ev(传参) || window.event;
- 需要使用事件对象的属性的时候,就需要获取事件对象
鼠标事件对象的属性
1、事件对象:
- button : 0 左键 1 滑轮 2 右键
2、获取当前鼠标位置
- clientX clientY (可视窗口的左上角为原点)
- pageX pageY (整个页面的左上角为原点)
- screenX screenY (电脑屏幕的左上角为原点)
跟随鼠标移动提示框案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>跟随鼠标移动提示框</title>
<style>
a {
display: block;
font-size: 20px;
margin: 20px;
width: 130px;
}
#msg {
width: 150px;
height: 30px;
background-color: gray;
color: white;
display: none;
position: absolute;
}
</style>
<script>
//创建一个数组,用于存放div标签的内容
let mgs = [
'唐太宗:哈哈哈',
'唐高宗:呵呵呵',
'唐玄宗:嘻嘻嘻',
'武则天:哈啊哈',
];
onload = function () {
//获取a标签对象
let a = document.getElementsByTagName('a');
//获取div
let div = document.getElementById('msg');
//遍历a标签给所有a标签添加鼠标移入时间
for (let i = 0; i < a.length; i++) {
//添加鼠标移入事件
a[i].onmouseover = function () {
div.style.display = 'block';
};
//添加移出事件
a[i].onmouseout = function () {
div.style.display = 'none';
};
//添加div跟随鼠标移动事件
a[i].onmousemove = function (ev) {
//获取事件对象
let e = ev || event;
div.style.left = e.clientX + 5 + 'px';
div.style.top = e.clientY + 5 + 'px';
div.innerText = mgs[i];
};
}
};
</script>
</head>
<body>
<a href="#">唐太宗</a>
<a href="#">唐高宗</a>
<a href="#">唐玄宗</a>
<a href="#">武则天</a>
<div id="msg"></div>
</body>
</html>
修改键
- shiftKey:按下为true,默认为false
- AltKey
- CtrlKey
- metaKey:win系统:按下Windows键为true,macOS:按下command键为true
键盘事件对象的属性
- keyCode 键码
which
格式:var which = e.which || e.keyCode
只在keydown下支持 - charCode 字符码
which
格式:var which = e.which || e.charCode
只在keypress下支持
目标对象和this
- target 目标对象/触发对象
IE8一下不兼容,whindow.event.srcElement
this和baievent.target的区别:
this返回的是绑定事件的对象(元素);e.target返回的是触发事件的对象(元素)。
简单来说,this:哪个元素绑定了这个点击事件,就返回哪个元素;e.target:点击了哪个元素,就返回哪个元素。
- 事件冒泡:由里向外逐级触发
- 事件捕获:由外向里逐级触发
- 事件对象的属性和方法
阻止事件冒泡:浏览器兼容问题canceBubble = true 或 stopPropagation()
跟随鼠标移动案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>跟随鼠标移动</title>
<style>
* {
margin: 0px;
padding: 0px;
}
div {
position: absolute;
width: 20px;
height: 20px;
background-color: red;
border-radius: 50%;
}
</style>
<script>
onload = function () {
//获取到所有的div
var divs = document.getElementsByTagName('div');
//添加鼠标移动事件
document.onmousemove = function (ev) {
let e = ev || event;
for (let i = divs.length - 1; i > 0; i--) {
divs[i].style.left = divs[i - 1].offsetLeft + 'px';
divs[i].style.top = divs[i - 1].offsetTop +'px';
}
divs[0].style.left = e.clientX + 'px';
divs[0].style.top = e.clientY +'px';
};
};
</script>
</head>
<body>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</body>
</html>
阻止右键菜单
阻止超链接行为
拖拽节点案例
/**
* 元素节点跟着鼠标拖动(可以越界)
* @param {拖拽的节点} node
*/
function drag(node) {
node.onmousedown = function (ev) {
let e = ev || event;
var omlift = e.clientX - node.offsetLeft;
var omtop = e.clientY - node.offsetTop;
//鼠标移动事件
document.onmousemove = function (ev) {
let e = ev || event;
node.style.left = e.clientX - omlift + 'px';
node.style.top = e.clientY - omtop + 'px';
};
};
document.onmouseup = function() {
document.onmousemove = null;
}
}
不可越界
/**
* 元素节点跟着鼠标移动(不能越界)
* @param {拖拽的结点} node
*/
function drag(node) {
node.onmousedown = function (ev) {
let e = ev || event;
var omlift = e.clientX - node.offsetLeft;
var omtop = e.clientY - node.offsetTop;
//鼠标移动事件
document.onmousemove = function (ev) {
let e = ev || event;
//拖拽后div的坐标
let l = e.clientX - omlift;
let t = e.clientY - omtop;
//出界控制
if(l <= 0) {
l = 0;
}
let windowWidth = document.documentElement.clientWidth || document.body.clientWidth;
if(l >= windowWidth - node.offsetWidth) {
l = windowWidth - node.offsetWidth
}
if(t <= 0) {
t = 0;
}
let windowHeight = document.documentElement.clientHeight || documetn.body.clientHeight;
if(t >= windowHeight - node.offsetHeight) {
t = windowHeight - node.offsetHeight;
}
node.style.left = l + 'px';
node.style.top = t + 'px';
};
};
document.onmouseup = function() {
document.onmousemove = null;
}
}
事件委托
实现步骤:
- 找到当前节点的父节点或者祖先节点
- 将事件添加到你找到的这个父节点或者祖节点上
- 找到触发对象,判断触发对象是否是想要的触发对象,进行后续操作
arguments
每一个函数内部都有一个arguments,系统内置的。
1、用来存储实参
属性 :arguments.length输出当前里面存储的参数个数
访问某一个数据:arguments[下标]: 从零开始