JavaScript
1. 什么是JavaScript
JavaScript是一门脚本语言(一个后端人员,必须要精通JavaScript)
脚本语言和编程语言区别,不需要编译链接,是直接解释型语言,在含有解释器的环境中直接可以运行。主要用于管理,方便部署.
2. 快速入门
2.1 引入javaScript
1.内部标签使用(标签成对出现)
<script>
//....
<script>
- 引入js文件
<script src="**.js"></script>
例:
<!DOCTYPE html>
<html lang ="en">
<head>
<meta charset="UTF-8">
<title>javaScript</title>
<!--script标签内写js,可以放在body里,但通常放head里-->
<!-- 写法一,直接html里写-->
<script>
alert("hello,world");
</script>
<!--写法二,引入script标签必须成对出现
<script src="js/js1.js"></script>-->
<!--这种不常用,type不标注默认也是javaScript
<script type="text/javascript">
alert("hello,world");
</script>-->
</head>
<body>
</body>
</html>
2.2 基本语法入门
区分大小写,变量定义用var没有其他类型,注释等和java语法一样
<!DOCTYPE html>
<html lang ="en">
<head>
<meta charset="UTF-8">
<title>js</title>
<script>
//1.不同于java定义变量不需要设置类型,直接是var
var score=75;
var name="happy";
//2.条件控制
if(score >60 && score<70){
alert("60-70");
}else if(score>70&& score<80){
alert("70-80");
}else{
alert("other");
}
/* 调试的时候在浏览器中审查元素->consle选项
1. 可以直接输入alert(变量名)查看变量值
2. 输入console.log(变量名)相当于system.out.println
*/
</script>
</head>
<body>
</body>
</html>
调试,浏览器控制台的使用:
- 使用console调试
- 使用source选项卡
点中哪行就是在该行设置断点,然后刷新就可以运行
3.使用application选项卡
查看存在浏览器里的数据
- 使用Network用来抓包
- 使用Element调网页div等元素
2.3 数据类型
数值,文本,图形,音频,视频...
- 变量
var 定义不能以数字开头 - number
--js不区分整数小数还是科学计数法,NAN表示not a number, Infinity表示无限大 - 字符串
'abc' "abcd",单引号 双引号都行,也可以是各种转义字符 - 布尔值
true,false - 逻辑运算
&&,||, ! - 比较运算
= 赋值
== 等于(类型不一样,值一样算相等)
=== 绝对等于(类型不一样值一样,不等)
这是JS的一个缺陷,坚持不要使用两个等于号,作比较用三个等于号
须知:- NAN===NAN返回为false,这个值与所有值都不相等,包括自己
- 只能使用isNAN来判断一个值是不是NAN
浮点数问题:
console.log((1/3)==(1-2/3))返回false,和java一样会有精度损失,尽量避免使用浮点数进行运算
console.log(Math.abs(1/3-(1-2/3))<0.0000001)
- null和undefined
null是空
undefined未定义 - 数组
java的数组必须是一系列相同类型的对象,js中不需要这样
//保证代码的可读性,尽量使用[]中括号的写法
var arr = [1,2,3,4,'hello',null,true];
new Array(1,2,3,4,"hello",null,true);
取数组下标如果越界了,提示undefine.
- 对象
对象定义使用大括号,数组用中括号
每个属性使用逗号隔开,最后一个不需要添加
var person = {
name:"xiaoming",
age:3,
tags:['js','java','web','...']
}
取对象的值
>person.age
3
>person.name
"xiaoming"
2.4 严格检查格式
前提设置IDEA支持ES6语法(Settings->JavaScript->version ECMAScript6)
'use strict':严格检查模式,写在javaScript的第一行,预防JavaScript的随意性导致产生一些问题
局部变量建议使用Let来定义
<script>
'use strict';
let i=1;
</script>
3. 数据类型
3.1 字符串
- 正常字符串我们使用单引号或者双引号包裹,特殊字符使用转义字符\
\'
\n
\t
\u4e2d \u#### unicode字符
"\x41" Ascii字符
- 多行字符串编写
使用反引号包裹多行字符(tab和ESc中间的字符)
`hello
你好
天天好心情`
- 模板字符串
ES6里面直接可以${变量名}取出变量值
let name ="xiaoming";
console.log("你好,${name}");
- 字符串长度
console.log(str.length); - 字符串不可变,不同于java,它的每个字符可以通过下标取出来
student[0]=1;这种赋值失败的,不能该改变student这个字符串 - 大小写转换
toUpperCase()
toLowerCase() - indexOf()
- subString
subString(1)从第一个字符到最后
subString(1,3) [1,3)
3.2 数组
Array可以包含任意的数据类型
var arr ={1,3,'hello',4,7,10};
arr[0]=6;
console.log(arr);
- 长度
arr.length
注意:假如给arr.length赋值,数组大小就会发生变化,如果赋值过小,元素就会丢失 - indexOf 通过元素获得下标索引
- slice()类似于substring,截取Array的一部分,返回一个新数组
- push/pop
push 压入元素到数组尾部,pop弹出尾部元素 - unshift/shift
从数组头部添加/删除元素 - sort()排序
- reverse()元素反转
- concat()拼接
注意:concat并没有修改数组,只是返回一个新的数组 - 连接符 join
打印拼接数组,使用特定的字符出连接
var arr=['a','b','c'];
arr.join('-');
10.多维数组
arr=[[1,2],[3,4],[5,6]]
arr[1][1]
数组:存储数据(重要的是知道如何存,如何取,其他方法都可以自己实现)
3.3 对象
若干个键值对
var 对象名={
属性名:属性值,
属性名:属性值,
属性名:属性值
}
js中对象,{...}表示一个对象,键值对描述属性xxxx:xxxx,多个属性之间使用逗号隔开,最后一个属性不加逗号
js中所有键都是字符串,值是任意对象
- 对象赋值
person.name="xiaoming" - 使用一个不存在的对象属性,不会报错!undefined
person.haha
undefined - 动态的删除属性
delete person.name
true - 动态的添加属性,直接给新的属性赋值即可
person.haha="haha" - 判断某个属性是否在这个对象中 xx in xxx
'age' in person
true
//继承
'toString' in person
true
- 判断一个属性是否是这个对象自身拥有的 hasOwnProperty
person.hasOwnProperty("toString")
false
3.4 流程控制
- if 判断
- for循环, while, do-while
- forEach循环
var age={13,2,12,2,323,454,234,1,45}
//函数
age.forEach(function(value)){
console.log(value)
}
- for ... in
//for(var index in object){}
for (var num in age){
if(age.hasOwnProperty(num)){
console.log('存在')
console.log(age[num])
}
}
对新增的特性存在一个bug
var arr = [3,4,5];
arr.name ="213";
for( let x in arr){
console.log(x)
}
新增的会输出name,这是个遗留下来的bug,所以es6里引入了iterator
5. for.. of
var arr = [ 3, 4,5]
for(var x of arr){
console.log(x)
}
//遍历map
var map = new Map([["tom",100],["jack",90],["haha",80]]);
for(let x of map{
console.log(x)
}
3.5 Map和Set
Map: get获取值,set设置值或者新增
//ES6新特性
var map = new Map(['tom',100],['jack',90],['haha',80]]);
var name = map.get('tom');
map.set('admin',123456);
map.delete('tom')
Set: 无序不重复的集合
var set = new Set([3,1,1,1,1])//set 可以去重
set.delete(1);
console.log(set.has(3));//是否包含某个元素
3.6 Iterator迭代器
略
4. 函数
4.1 定义函数
- 定义方式一
function abs(x){
if(x>=0){
return x;
}else{
return -x;
}
}
一旦执行return代表函数结束,如果没有执行return,函数执行完也会返回结果,结果是undefined
- 定义方式二
var abs = function(x){
if(x>=0){
return x;
}else{
return -x;
}
}
function(x){...}这是一个匿名函数,但是可以把结果赋值给abs,通过abs可以调用函数
- 调用函数
abs(-10); - 参数问题
js可以传递任意个参数,也可以不传递参数
参数进来是否存在问题?假设不存在参数,如何规避?
手动检查,抛出异常
var abs = function(x){
if(typeof x!== 'number'){
throw 'Not a Number';
}
if(x>=0){
return x;
}else{
return -x;
}
}
- arguments
'arguments'是一个js免费赠送的关键字,代表传递进来的所有参数,是一个数组
var abs = function(x){
console.log("x=>"+x);
for(var i=0;i<arguments.length;i++){
console.log(arguments[i]);
}
}
问题 arguments包含所有的参数,有时候想使用多余的参数来进行附加操作,需要排除已有的参数
- rest
ES6引入的新特性,获取除了已经定义的参数之外的所有参数
以前
if(arguments.length>2){
for(var i =2;i<arguments.length;i++){
//截取后面的参数,前提事知道已经定义了几个
}
新特性
function aaa(a,b,...rest){
console.log(a);
console.log(b);
console.log(rest);
}
rest参数只能写在最后面,必须用...标识(可变参数)
4.2 变量的作用域
- 在js中var定义的变量是有作用域的,假设在函数体中声明,在函数体外是不可以使用的(非要使用的话,研究下闭包)
- 两个函数内部各自定义了相同名字的变量,使用起来不会冲突
- 内部函数可以访问外部函数的成员,反之则不行
- 内部函数变量和外部函数变量重名,按照从'内'向'外'查找,内部使用自己定义的变量(覆盖外部的)
提升变量作用域
function a(){
var x='x'+y;
console.log(x);
var y ='y';
}
结果:xundefined
说明,js执行引擎,自动提升了y的声明,但是不会提升它的赋值
function a(){
var y;
var x ='x'+y;
console.log(x);
car y='y';
}
这是javaScript建立之初就存在的特性,建立规范所有代码在函数之初定义变量。
- 全局函数
略 就是定义在script里,非局部块内的函数 - 全局对象Window
var x ='xxx';
alert(window.x)//默认所有全局变量都被绑定在window里
window.alert(window.x)
js实际上只有一个全局作用域,任何变量(函数也可以视为变量)全局的都被绑定在window对象上,如果往上找也没找到,就会报错ReferenceError
- 规范
由于所有全局变量都被绑定到windows上,如果不同Js文件有相同的全局变量,冲突怎么解决?
//自己定义的唯一全局变量
var kuangApp ={};
//把其他变量绑定上去
kuangApp.name="xiaoming";
kuangApp.add=function(a,b){
return a+b;
}
把自己的代码全部放入自己定义的唯一空间名字中,降低全局命名冲突的问题(不直接绑定到window对象上)
扩展jQuery就是这么做的jQuery.xxx简写${}
- 局部作用域let
function aaa(){
for(var i=0;i<100;i++){
console.log(i);
}
console.log(i+1);//问题i出了作用域还可以用,输出了101,是js的bug
}
引入let局部作用域解决这个问题
function aaa(){
for(let i=0;i<100;i++){
console.log(i);
}
console.log(i+1);//报错,i is not defined
}
建议使用let去定义局部变量
- 常量const
在ES6之前定义常量:只要用全部大写命名的变量就是常量,只是个口头约定,人为还是可以修改使用
现引入const来定义常量
const PI ='3.14';
4.3 方法
方法就是把函数放在对象里面
var person = {
name:"xiaoming",
birth:2000,
//方法,age是key
age:function(){
var now = new Date().getFullYear();
return now - this.birth;
}
}
调用方法要写括号person.age()
this 表示调用该方法的对象,上述代码可以拆开写
function getAge(){
var now = new Date().getFullYear();
return now - this.birth;
}
var person = {
name:"xiaoming",
birth:2000,
//方法
age:getAge
}
getAge()NaN window是没有getAge这个方法的
person.age() OK
- apply
不同于java,js中this的指向是可以控制的,js里所有函数都有apply方法,有两个参数,第一个是想要指向的对象,第二个是参数
getAge().apply(person,[]) 这样调用就可以使用了。
此时this指向了person对象,没有参数参数为空[]
5 内部对象
- 标准对象
typeof 123
"number"
typeof NaN
"number"
typeof true
"boolean"
typeof "123"
"string"
typeof[]
"object"
typeof{}
"object"
typeof Math.abs
"function"
typeof undefined
"undefined"
5.1 Date
基本使用
var now = new Date();
now.getFullYear();年
now.getMonth();月 0~11
now.getDate();日
now.getDay();星期
now.getHours();时
now.getMinutes();分
now.getSeconds();秒
now.getTime(); 时间戳世界统一,从1970 1.1 0:00:00开始的毫秒数
console.log(new Date(1578106175991))//时间戳转化为时间
转换
now = new Date(1578106175991)
Sat Jan 04 2020 10:49:35 GMT+0800 (China Standard Time)
now.toLocaleString()
"1/4/2020, 10:49:35 AM"
now.toGMTString()
"Sat, 04 Jan 2020 02:49:35 GMT"
5.2 JSON
JSON是一种轻量级的数据交换格式。有简洁的层次结构,易于人阅读和编写,同时也易于机器解析和生成.
在JavaScript一切皆为对象,任何js支持的类型都可以转化为JSON来表示
格式:
- 对象都用{}
- 数组都用[]
- 所有键值对,都是用key:value
JSON和js对象的转换
var user ={
name:"zhangsan",
age:"12",
home:"chengdu"
}
//转换为json字符串
JSON.stringify(user);
//转换为对象
var obj = JSON.parse('{"name":"zhangsan","age":"12","home":"chengdu"}')
JSON和js对象区别
var obj = {a:'hello',b:'hellob'}//对象key,value类型不限制
var json='{"a":"hello","b":"hellob"}'//json key value都是string
5.3 Ajax(略后面讲)
- 原生的js写法 xhr异步请求
- jQuery封装好的方法${"#name"}.ajax
- axios请求
6. 面向对象编程
6.1 什么是面向对象
javascript,java,c#...面向对象
类 ----- 模板 (javascript 类对应原型对象)
对象 ---- 具体实例
- 原型:
将对象B的__proto__指向另一个对象A,就可以调用A中的方法属性
js里原型指向一个对象相当于java里的父类,各个对象之间可以互为原型
var user ={
name:"zhangsan",
age:"12",
run: function(){
console.log(this.name+"run...");
}
}
var xiaoming = {
name:"xiaoming"
}
//小明的原型是user
xiaoming.__proto__= user;//_按两下
xiaoming.run();//小明就可以跑了
- Class 继承
class关键字是在ES6中引入
function Student(name) {
this.name = name;
}
//给student新增一个hello方法
Student.prototype.hello = function(){
alert('hello')
}
现在ES6中
1.定义一个类,属性,和方法
class Student{
constructor(name){
this.name = name;
}
hello(){
alert("hello")
}
}
var xiaoming = new Student("xiaoming");
var xiaohong = new Student("xiaohong");
继承也遵守java语法,但本质上还是用的原型
class pupil extends Student{
constructor(name,grade){
super(name);
this.grade = grade;
}
myGrade(){
alert("我是一个小学生")
}
}
var xiaolan = new pupil("xiaolan",3)
- 原型链
reference https://www.cnblogs.com/loveyaxin/p/11151586.html
7 操作BOM对象(重点)
- 浏览器介绍
Javascript:能够在浏览器中运行的脚本
BOM:浏览器对象模型
有自己内核的浏览器- IE6~11
- Chrome
- Safari
- FireFox
三方
- QQ 浏览器
- 360 浏览器 (极速模式,兼容模式就是在切换内核,如IE)
常用的浏览器BOM对象 - Window对象(重要)
window代表浏览器窗口,除此之外它代表全局作用域。
window.alert("hell")
undefined
window.innerHeight
969
window.innerWidth
893
window.outerHeight
1040
- Navigator
Navigator封装了浏览器的信息
navigator.appName
"Netscape"
navigator.appVersion
"5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36 Edg/91.0.864.54"
navigator.userAgent
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36 Edg/91.0.864.54"
navigator.platform
"Win32"
通常不使用navigator对象信息来编码判断,因为它里面的值可以人为修改,用它来判断是否是windows电脑浏览还是在手机浏览,是不准确的
- screen
可以获取计算机屏幕信息
screen.width
1920
screen.height
1080
- location(重要)
代表当前页面的URL信息, 常用的属性方法如下
host: "www.baidu.com"
href: "https://www.baidu.com/"
protocol: "https:"
reload: ƒ reload() //刷新网页,重新加载
//设置新的地址,访问A的网站js里有这段代码,就会跳到B网站
location.assign("https://cn.bing.com/?scope=web&FORM=ANNTH1")
- document
document代表当前的页面,HTML DOM文档树- document.title //页面标题
- 获取具体的文档树节点
document.getElementById('app') - 获取cookie
document.cookie
劫持cookie
恶意网站在js里获取你的cookie上传到它的服务器里
服务器端可以设置cookie:httpOnly,那么通过js脚本将无法读取到cookie信息
- history
代表浏览器的历史记录,不推荐使用
history.back() 后退
history.forward()前进
8. 操作DOM对象(重点)
- 核心
浏览器网页就是一个DOM树形结构
可以结合选择器获取DOM节点,实现动态更新增删改 - 获取DOM节点
document原生方式可以直接调用如下代码:
var domElement = document.getElementByTagName('h1')
document.getElementById('p1')
document.getElementByClassName('p2')
使用JQuery可以简化写法 - 更新节点
- 操作文本
- domElement.innerText="123"修改文本的值
- domElement.innerHTML='123'可以解析的html文本
- 操作css样式
- domElement.style.color = 'yellow';
- domElement.style.fontSize='20px';
- domElement.style.padding = '2em';
- 操作文本
- 删除节点
删除步骤:先获取父节点,然后再删除当前节点
var self = document.getElementById('p1')
var father = self.parentElement;
father.removeChild(p1);
注意:删除多个节点的时候,children是动态变化的,大小是不断在减少的
如,假设father下只有三个节点,如下方式删除是错的,
删除0后已经就两个节点了,[1]是原来的[2],没有2了
father.removeChild(father.children[0])
father.removeChild(father.children[1])
father.removeChild(father.children[2])
- 插入节点
使用innerHTML/innerText原来是空的那么就相当于插入了,原来非空则覆盖原有的
所以通常用追加的方式插入- 追加
domElementA.appendChild(domElementB) - Insert插入
list.insertBefore(newchild,oldchild); //list里的
- 追加
- 创建一个新的dom元素
可以创建一个新的dom对象来追加
var newP = document.createElement('p')//创建一个P标签
newP.id = 'newP';
newP.innerText='hello,a luo';
list.appendChild(newP);
使用setAttribute方法可以设置任何属性,更好一点
//例<script type ="text/javascript" src=""></script>
var myScript = document.createElement('script');
myScript.setAttribute('type','text/javascript')
9. 操作表单
- 表单 用来提交信息
- 文本框 text
- 下拉框 select
- 单选框 radio
- 多选框 checkbox
- 密码框 password
- 隐藏域 hidden
...
- 获取表单项的值,修改/设置该项值
<form action="post">
<span>用户名:</span> <input type="text" id="username">
<!--多选框,单选框的值就是定义好的value值-->
<span>性别:</span> <input type="radio" name="sex" value="man" id="boy">男</input>
<input type="radio" name="sex" value="woman" id="girl">女</input>
</form>
<script>
var inputText = document.getElementById("username");
//得到输入框的值
inputText.value;
//修改输入框的值
inputText.value=9080;
var boy_radio = document.getElementById("boy");
var girl_radio = document.getElementById("girl");
//判断单选框或者复选框是否被选中用checked,true为选中,而不是直接取value
boy_radio.checked
//修改值选中女
girl_radio.checked=true;
</script>
- 提交表单
- 提交表单可以用form上的onsubmit属性来实现,注意onsubmit要return,true的时候会成功提交
- 利用button的onclick来手动提交
注意所有表单提交的数据项,必须要要有name和value,没有name的是不会提交的
处理密码,使其密文提交给后台
- 将password md5加密后重新赋值给该dom元素,缺点提交的一瞬间,password回写变长
- 使用隐藏域,原来的inputpassword输入框不设置名字,隐藏域的input值对inputpassword实施md5加密
这样原来的明文不会提交,真正提交的是隐藏域的值,抓包看不到明文
<body>
<!--
表单绑定提交事件
onsubmit绑定一个提交检测的函数true, false
将这个结果返回给表单
-->
<form action ="https://www.baidu.com/" method="post" onsubmit="return aaa()">
<p>
<span>用户名:</span> <input type="text" id="username" name="username" >
</p>
<p>
//<span>密码:</span> <input type="password" id="password" name="password">
<span>密码:</span> <input type="password" id="password">
</p>
<input type="hidden" id=“md5-password” name="md5-password">
<!--绑定事件
<button type="submit" onclick="aaa()">提交</button>
-->
<button type="submit" >提交</button>
</form>
<script>
function aaa(){
var uname = document.getElementById("username");
var upwd = document.getElementById("password");
//加密后写回框里
//upwd.value = md5(upwd.value);
var md5pwd= document.getElementById("md5-password");
md5pwd.value = md5(upwd.value);
console.log(uname.value);
//可以校验判断表单内容,true就是通过提交,false就是终止提交
return true;
}
</script>
</body>
10. jQuery
JQuery库:里面存了大量的javascript函数
10.1 获取jQuery
- 官网下载
第一个版本上线的时候用,第二个开发时用
- 使用jquery CDN(内容分发网络) 可以找到在线引用jquery的地址
10.2 语法
$(选择器).事件(事件函数体)
$(selector).action()
例
<!DOCTYPE html>
<html lang ="en">
<head>
<meta charset="UTF-8">
<title>js</title>
<!--在线的cdn引入-->
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<!--导入本地下载的jquery
<script src="lib/jquery-3.6.0.js"></script>-->
</head>
<body>
<a href="" id="test-jquery">点我</a>
<script>
//不用这样写document.getElementById('test-jquery');
//选择器和css里一样
$('#test-jquery').click(function(){
alert('hello,jquery');
})
</script>
</body>
</html>
10.3 jquery选择器
css中的选择器jquery都能用
$('p').click() //标签 选择器
$('#id').click()//id选择器
$('.class').click()//类选择器
更多选择器,查看文档工具站 https://jquery.cuishifeng.cn/
10.4 事件
鼠标事件、键盘事件、其他事件
例获取鼠标坐标
mousemove事件处理函数会被传递一个变量——事件对象,其.clientX 和 .clientY 属性代表鼠标的坐标
<style>
#divMove{
width:500px;
height:500px;
border: 1px solid red
}
</style>
<body>
<!--获取鼠标的当前坐标-->
mouse:<span id ="mouseMove"></span>
<div id="divMove">
在这里点击试试
</div>
<script>
//当网页元素加载完毕之后,响应事件
//$(document).ready(function(){})-->简化$(function(){})
$(function(){
$('#divMove').mousemove(function(e){
$('#mouseMove').text('x:'+e.pageX+'y:'+e.pageY);
}
)
})
</script>
10.5 操作DOM
- 节点文本操作
//document.getElementById()...
//无参获得值,有参设置值
$('#test-ul li[name="python"]').text();
$('#test-ul').html()
- css操作
直接调用.css键值对即可
$('#test-ul li[name="python"]').css({"color":"red","background":"yellow"});
- 元素的显示和隐藏:本质是display:none
$('#test-ul li[name="python"]').show()
$('#test-ul li[name="python"]').hide()
- 文档处理略
$(document)//具体查看工具网站
- 扩展前端小技巧
- 如何巩固js(看jQuery源码,看游戏源码去源码之家,看别人做好的前端游戏源码)
- 巩固HTML CSS(扒网站,全部down下来,然后删删减减修改看对应效果)
友人C
layui-layer弹窗(layui-文档->弹出层->layer网址https://layer.layui.com/)
Element-ui(https://element.eleme.cn/#/en-US/component/color)清新的组件
Bootstrap就相对稳重风
ant.design https://ant.design/components/overview/
(注:6)