JavaEE03_JavaScript
1、使用javascript
1.1 js引入
Javascript代码写在script标签内,且script标签s必须成对出现,不能自闭和,不然会出错
<script type="text/javascript">
</script>
引入外部 文件名.js代码(src后跟路径)
<script src="js/qj.js"></script>
1.2 基本语法
语法基本与java一致,不过js的变量只有var和let
var是全局bianl
let是局部变量
可以通过console.log()在浏览器控制台输出(浏览器F12)
alert()弹出弹窗
var的基本测试
/**
* 基本类型var:
* 1.number:js不区分小数和整数
* 123 整数123
* 123.1 浮点数123.1
* 1.123e3 科学计数法
* -99 负数
* NaN not a number
* Infinity 表示无限大
* 2.字符串:'abc' "abc"
* 3.布尔值:true false(与java用法一样)
* 4.逻辑运算:&&
* ||
* !
* 5.比较(重要)
* = 赋值
* == 等于(类型不一样,值一样,也会判断为true)
* === 绝对等于(类型一样,值一样才会判断为true)
* 避免使用==,容易出问题
* 6.NaN 与所有数值都不相等,包括自身
* 只能通过NisNaN(NaN)来判断这个数是否为NaN
*
* 7.浮点数问题
* console.log((1/3)===(1-2/3)); 因为精度会缺失,所以输出false
console.log(Math.abs((1/3)-(1-2/3))<0.00000001); 精度小于0.00000001,默认两个相等
* 8.null和undefined
* null 空
* undefined 未定义
* 9.数组:java必须是一系列相同类型的对象,在JS中并不需要这样,因为var是所有类型,如果越界就会undefined
* var arr=[1,2,3,4,'name',true,null];
* console.log(arr[1]);
* 10.对象:对象是大括号,数组是中括号
* 每个属性之间使用逗号隔开,最后一个不需要添加
* 输出:person.name
*/
1.3严格检查模式
<script>
'use strict'
</script>
前提:IDEA 需要设置支持ES6语法
‘use strict’ 严格检查模式,预防js的随意性导致产生的一些问题,比如直接写i=1;没有去定义它为 var或let也是可以使用的,且默认是var
必须写在javascript的第一行
2、js详解
2.1字符串
-
正常字符串一般使用单引号或双引号包裹。
-
转义字符:
/**
*
* 2、转义字符
* \'
* \n
* \t
* \u4e2d // \u#### Unicode编码
* \x41 //ascll
*
*/
console.log('a\'');
console.log("a\nd");
console.log("\u4e2d\n\x41");
-
多行字符串编写(tab上面的 ` 键)
let msg= ` xiaosi world ` console.log(msg)
-
模板字符串
let name="xiaosi"; let msg2=`你好,${name}`
-
字符串长度:.length
-
字符串的不可变性
var myStr = "Bob"; myStr[0] = "J";//这是无法实现的,字符串创建完单个值是无法改变的,要改变要重新给它赋一个值 var myStr = "Bob"; myStr = "Job";
-
大小写转换
.toUpperCase()转大写
.toLowerCase()转小写
-
显示某字符的下标
.indexOf(’ ')
-
substring
.substring(n,m) 从第n个字符串截取到最后m个字符串,若m没写就是到最后一个字符串[n,m)
2.2 数组
-
长度:给arr.length赋值,数组大小就会发生变化,自动添加undefined,如果赋值过小,元素就会丢失
arr.length=10;
-
indexOf,通过元素获得下标索引,字符串的"1"和数字的1是不一样的,字符串的"1"是获取此字符串的下标值,1是获取下标1的字符串
-
slice()截取Array的一部分,返回一个新数组,类似String中的substring
数组.slice(n) :从下标n开始截取,到最后一个字符,且原数组不会发生改变
-
push pop
arr2.push("a","b");//压入尾部 console.log(arr2); arr2.pop();//弹出尾部 console.log(arr2);
-
unshift() shift()
arr2.unshift("a","b");//压入头部 console.log(arr2); arr2.shift();//弹出头部 console.log(arr2);
-
排序sort()
sort() 方法用于对数组的元素进行排序。
排序顺序可以是字母或数字,并按升序或降序。
默认排序顺序为按字母升序。
-
元素反转
.reverse()
-
拼接 concat,并没有修改数组,只是会返回一个新的数组
arr3.concat(arr2) //不会改变原数组
-
连接符join,打印拼接数组,使用特定的字符串连接
console.log(arr3.join('-')); //结果C-B-A
-
多维数组
let arr4=[ [1,2], [3,4], ["5","6"] ]; console.log(arr4[1][1]);
2.3 对象
var 对象名={
属性名:属性值,
属性名:属性值
}
var person={
//多个属性用逗号隔开,最后一个不加逗号
name:'xiaosi',
age:3,
email:"1170035083@qq.com",
score:0
}
//对象赋值
person.name='haishi';
//使用一个不存在的对象属性,不会报错,会undefined
console.log(person.haha);
//动态删除属性,通过delete删除对象属性,可以在控制台直接删除
delete person.score;
//动态添加,直接给新的属性添加值就可以
person.haha="haha";
//判断属性值是否在对象中 xxx in xxx
console.log('name' in person);
console.log('toString' in person);//true 可以知道它父类的方法
//判断一个属性是否是这个对象自身拥有的hasOwnProperty
console.log(person.hasOwnProperty('name'));//true
console.log(person.hasOwnProperty('toString'));//false
Object的hasOwnProperty()
方法返回一个布尔值,判断对象是否包含特定的自身(非继承)属性。
pereson里面有name属性,虽然他的父类有toString但是他自己没有,所以是false
2.4 流程控制
除了foreach,其余的与java一致
//判断
var age=3;
if(age>3){
alert("haha");
}else{
alert("kuwa");
}
//循环
while(age<100){
age++;
console.log(age);
}
//for循环
for(let i=100;i<110;i++){
console.log(i);
}
//foreach循环,对象可以value.xxx
var arr=[1,2,3,34,54,6,7,12,32];
arr.forEach(function (value) {
console.log(value);
})
/*
* 在java中,for(Type str:el){}
* */
2.5 Map和Set
与java一致
//ES6的新特性
//学生的成绩,学生的名字
var map=new Map([['tom',100],['jack',90],['haha',80]]);
var name=map.get('tom');
console.log(name);
map.set('admin',10);
console.log(map);
map.delete('tom');
var set=new Set([3,1,1,1,1]);//set可以去重
set.add(2);
console.log(set);
set.delete(1);
console.log(set);
console.log(set.has(3));//里面是否包含x
2.6 iterator
// for in只能打印下标,新增下标不能正常显示下标,会直接显示里面的值
//若for in要打印数值的话,用下面实现
for(var num in arr){
console.log(arr[num]);//这里的num只是下标
}
//通过for of来打印数 遍历map 遍历set都是一样的
for(let x of arr){
console.log(x);
}
2.7 定义函数
//定义方式1:
//绝对值函数,一旦执行到return就表示函数结束,返回结果
//如果没有执行return,函数执行完也会返回结果,结果是undefined
function aaa(x) {
if(x>=0){
return x;
}else{
return -x;
}
}
/定义方式2:(与上一种等效)
/*
* function(x) {...}是一个匿名函数,但是可以把结果赋值给abs,通过abs就可以调用函数
* */
var abs= function(x) {
if(x>=0){
return x;
}else{
return -x;
}
}
/**
* 参数问题:js可以传任意个参数,也可不传递参数
* 参数进来是否存在 假设不存在参数,如何规避(手动抛出异常)
*
运算数为数字 typeof(x) = "number"
字符串 typeof(x) = "string"
布尔值 typeof(x) = "boolean"
对象,数组和null typeof(x) = "object"
函数 typeof(x) = "function"
*/
function abc(x) {
if(typeof x!=='number'){
throw 'Not a Number';
}
if(x>=0){
return x;
}else{
return -x;
}
}
/**
* arguments是一个JS免费赠送的关键字,代表传递进来的参数,是一个数组
* 问题:arguments包含所有的参数,有时想使用多余的参数来进行附加操作,需要排除已有的参数
* 若传入多个参,这些参数就会被自动放入arguments数组中,可以直接从arguments中拿出来
*/
function bbb(x) {
console.log("x->"+x);
for(let i=0;i<arguments.length;i++){
console.log(arguments[i]);
}
if(x>=0){
return x;
}else{
return -x;
}
}
2.8 可变长参数
以前的写法:
//以前的写法,使用arguments来判断aaa()里到底输入了多少个值,因为js是一款极其不严谨的语言,就算你传入一
//百个值都不会报错。所以可以使用arguments来执行传入多参的方法
function aaa(a,b) {
console.log("a=>"+a);
console.log("b=>"+b);
if(arguments.length>2){
for(let i=2;i<arguments.length;i++){
console.log(arguments[i]);
}
}
}
由于ES6引入的新特性,可以直接写可变长参数:
//现在
function bbb(a,b,...rest) {//rest只能写在最后面,必须用...标识
console.log("a=>"+a);
console.log("b=>"+b);
console.log(rest);
}
2.9 变量的作用域
- 全局作用域:所有地方都可以访问
- 函数作用域:只能在函数内部访问
变量的声明:显示声明(var i=1;)和隐式声明(i=1;)
-
在函数体中声明的变量,在函数体外不能使用,要用得使用闭包
-
如果两个函数用了同一个变量名,只要在函数内部声明就不冲突
-
内部函数成员可以访问外部函数,外部不能访问内部
-
内部函数变量和外部函数变量重名的情况下,内部与外部重名的部分用内部的变量。。。。由内向外查找
-
假设外部存在这个同名的函数变量,则内部函数会屏蔽外部函数的变量
2.10 作用域的提升
下面的定义的变量上面可以调用(作用域提升),但是仅仅只是提升作用域,它的赋值并不会被提升上去。
var x='x'+y;
console.log(x);
var y='y';//结果:xundefined,js的执行引擎,自动提升了y的声明但是不会提升变量y的赋值,在js建立之初就存在的
//养成规范:所有的变量定义都放在函数的头部,不要乱放,便于代码维护
2.11 alert的一些方法
alert(a);
alert(window.a);//默认所有全局变量,都会自动绑定在Window对象上
window.alert(a);//alert()这个函数本身也是Window变量
//把alert方法赋予别的变量,原来的alert失效
var old_alert=window.alert; //把alert方法赋给一个变量,这个变量就有了alert的功能
old_alert('haishi');
//重写alert方法
window.alert=function () {
};
//恢复
window.alert=old_alert;
JS实际上只有一个全局作用域,任何变量(函数也可视为变量),假设没有在函数作用范围内找到,就会向外查找,
如果在全局作用域都没有找到,报错ReferenceError
2.12 自定义唯一全局变量
由于我们所有的全局变量都会绑定到我们的window上,如果不同的js文件使用了相同的全局变量,就会造成冲突。解决办法:自定义唯一全局变量,把自己的代码全部放入自己定义的唯一空间名字中,降低全局命名冲突的问题
//唯一全局变量
var XiaoSi={};
//定义全局变量或方法
XiaoSi.name='xiaosi';
XiaoSi.add=function(a,b){
return a + b ;
}
全局作用域冲突使用自定义全局变量来解决,而局部作用域冲突问题则使用let来解决。
2.13 常量
在ES6之前,定义常量:只有用全部大写字母命名的变量就是常量;建议不要修改这样的值,但实际上是可以随意修改的。ES6我们可以const来实现真正的常量(类似java的final)
const PI='3.14'; //只读变量
console.log(PI);
PI='3.1415';//报错Uncaught TypeError: invalid assignment to const 'PI'
2.14方法
方法就是把函数放在对象里面,对象只有两个东西:属性和方法
var xiaosi={
name:'小厮',
birth:1998,
//方法
age:function () {
//今年-出生的年份
var now=new Date().getFullYear();
return now-this.birth;
}
}
也可以在对象中引入外面的函数。
function getAge() {
var now=new Date().getFullYear();
return now-this.birth;
}
var xiaosi={
name:'小厮',
birth:1998,
//引入外部函数的方法
age:getAge
}
3、扩展
3.1 typeof
console.log(typeof 123); //查看后面的东西是什么类型的(这里是number)
3.2 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);
console.log(now.toLocaleString());//调用一个方法,而不是属性
//now.toGMTString()格林威治标准时间
3.3 Json
/**
* JSON一种轻量级的数据交换格式
* 具有层次结构
*
* 在JS中一切都是对象、任何js支持的类型都可以用JSON来表示
* 对象{}
* 数组[]
* 键值对key:value
*/
//对象转化为json字符串
var JSONUser=JSON.stringify(user);
//json字符串转化为对象,参数为JSON字符串
var obj=JSON.parse('{"name":"xiaosi","age":3,"sex":"男"}');
3.4 js的面对对象编程
/**
* 类:模板
* 对象:具体的实例
*
* 但在JS中,需要换一下思路:
* 原型:
*/
var user={
name:'xiaosi',
age:3,
run:function () {
console.log(this.name+" run...");
}
};
var Bird={
fly:function () {
console.log(this.name+" fly...");
}
};
var xiaoming={
name:'xiaoming' //无法直接调用run方法,会报错
};
/*
* 原型对象(实际上是继承)
* */
xiaoming.__proto__=user;//小明的原型是user,这是旧的方法,可以随意更换
xiaoming.run();
xiaoming.__proto__=Bird;
xiaoming.fly();
3.5 class的继承
在ES6之前无class关键字,所以要使用prototype往前面的函数添加新方法
prototype 属性使您有能力向对象添加属性和方法。
function Student(name) {
this.name=name;
}
//给student新增一个方法,要么改它的方法,要不如下获得它的原型增加...ES6之前的原生方法,不用记
Student.prototype.hello=function () {
alert('hello')
}
//ES6之后
//定义一个学生的类
class Student{
constructor/*构造器关键字*/(name) {
this.name=name;
}
hello(){
alert('hello');
}
}
var xiaoming=new Student('xiaoming');
xiaoming.hello();
console.log(xiaoming.name);
/**
* 继承
*/
class XiaoStudent extends Student{
constructor(name,grade) {
super(name);
this.grade=grade;
}
myGrade(){
alert('我是一个小学生');
}
}
var xiaohong=new XiaoStudent('xiaohong');
xiaohong.myGrade();
console.log(xiaohong);
3.6 原型与原型链
原型
在JavaScript中,每当定义一个函数数据类型(普通函数、类)时候,都会天生自带一个prototype
属性,这个属性指向函数的原型对象,并且这个属性是一个对象数据类型的值。
让我们用一张图表示构造函数和实例原型之间的关系:
原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中。
原型链
- 1.
__proto__
和constructor
每一个对象数据类型(普通的对象、实例、prototype
…)也天生自带一个属性__proto__
,属性值是当前实例所属类的原型(prototype
)。原型对象中有一个属性constructor
, 它指向函数对象。
function Person() {}
var person = new Person()
console.log(person.__proto__ === Person.prototype)//true
console.log(Person.prototype.constructor===Person)//true
//顺便学习一个ES5的方法,可以获得对象的原型
console.log(Object.getPrototypeOf(person) === Person.prototype) // true
image
- 2.何为原型链
在JavaScript中万物都是对象,对象和对象之间也有关系,并不是孤立存在的。对象之间的继承关系,在JavaScript中是通过prototype对象指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的链条,专业术语称之为原型链。
举例说明:person → Person → Object ,普通人继承人类,人类继承对象类
当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用。如果没有则去原型的原型中寻找,直到找到Object对象的原型,Object对象的原型没有原型,如果在Object原型中依然没有找到,则返回undefined。
我们可以使用对象的hasOwnProperty()
来检查对象自身中是否含有该属性;使用in
检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true
function Person() {}
Person.prototype.a = 123;
Person.prototype.sayHello = function () {
alert("hello");
};
var person = new Person()
console.log(person.a)//123
console.log(person.hasOwnProperty('a'));//false
console.log('a'in person)//true
person实例中没有a这个属性,从 person 对象中找不到 a 属性就会从 person 的原型也就是 person.__proto__
,也就是 Person.prototype中查找,很幸运地得到a的值为123。那假如 person.__proto__
中也没有该属性,又该如何查找?
当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层Object为止。Object是JS中所有对象数据类型的基类(最顶层的类)在Object.prototype上没有__proto__
这个属性。
console.log(Object.prototype.__proto__ === null) // true
4、BOM和DOM
DOM是一套操作HTML标签的API(接口/方法/属性)
BOM是一套操作浏览器的API(接口/方法/属性)
4.1 操作BOM对象
4.1.1 基本
BOM:浏览器对象模型
JS诞生就是为了能够让他在浏览器中运行
-
浏览器内核:
IE 6-11
Chrome
Safari
FireFox(Linux默认) -
三方:
QQ,360 -
window:
window代表浏览器窗口
window.innerHeight;
window.innerWidth;
window.outerHeight;
window.outerWidth;//浏览器的内宽高和外宽高,调整浏览器会改变
-
Navigator封装了浏览器的信息:
navigator.appName
“Netscape”
navigator.appVersion
“5.0 (Windows)”
navigator.userAgent
“Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0”
navigator.platform
“Win32”
大多数时候不会使用navigator对象,因为会被人为修改
不建议使用这些属性来判断和编写代码(例如if(navigator.appName=‘xxx’)之类的)
window.navigator;
- screen屏幕
screen.width;
screen.height;//像素
- location
/**
* location(重要)
* 代表当前页面的URL信息
* host: "localhost:63342" 主机
* href: "http://localhost:63342/JavaScript/lesson04/1.%E6%93%8D%E4%BD…87%8D%E7%82%B9%EF%BC%89.html?_ijt=onret8mf0ch9jg9gjfsdsv9vjv" 当前指向网页
* protocol: "http:" 协议
* reload: reload() 重新加载网页
*/
console.log(location);
//设置新的地址,直接转到assign指向的网站
location.assign('https://www.baidu.com');
4.1.2 document
/**
*document代表当前页面, HTMl DOM树
*/
var dl=document.getElementById('app');//获取具体的文档树节点
/**
* 获取cookie
* 劫持cookie原理
* 恶意人员:获取你的cookie上传到他的服务器
*
* 服务器端可以设置cookie:httpOnly(只读)
*/
console.log(document.cookie);
4.1.3 history
history代表浏览器的历史记录,不建议使用
history.back() //后退
history.forward() //前进
4.2 操作DOM对象
4.2.1 基本
DOM:文档对象模型
核心:
浏览器网页就是一个DOM树形结构
1.更新:更新DOM节点
2.遍历dom节点:得到DOM节点
3.删除:删除一个DOM节点
4.添加:添加一个新的节点
要操一个dom节点就必须获得这个dom节点
4.2.2 获得DOM节点
document
<body>
<div id="father">
<h1>标题一</h1>
<p id="p1">p1</p>
<p class="p2">p2</p>
</div>
<script>
//对应CSS选择器,获得dom节点
var h1=document.getElementsByTagName('h1');
var p1=document.getElementById('p1');
var p2=document.getElementsByClassName('p2');
var father=document.getElementById('father');
var childrens=father.children; //获取父节点下的所有子节点
//father.firstChild第一个节点
//father.lastChild最后一个节点
//这是原生代码,之后尽量使用jQuery();
</script>
</body>
4.2.3 更新节点
var id1=document.getElementById('id1');
id1.innerText='456';//修改文本的值
id1.innerHTML='<strong>456</strong>';//可以解析HTML文本标签
//可以进行CSS操作,在网页上可以直接用JS进行修改界面
id1.style.color='yellow';
id1.style.fontSize='200px';//不支持-,用驼峰命名
4.2.4 删除节点
/**
* 删除节点的步骤:先获取父节点,再通过父节点删除自己
* 第一种标准流程
*/
var self=document.getElementById('p1');
var father=self.parentElement;
//father.removeChild(self);
/**
* 方法2:通过下标移除,要注意删除多个节点的时候children是在时刻变化的
*/
//father.removeChild(father.children[1]);//你删除完一后原来的2就变成一
4.2.5 插入节点
我们获得了某个Dom节点,假设这个Dom节点是空的,我们通过innerHTML就可以增加一个元素了,但是这个Dom节点已经存在元素了,我们就不能这么干,会覆盖,可以使用追加:append
var
js=document.getElementById('js'),//已存在的节点
list=document.getElementById('list');
//list.appendChild(js);//控制台输入,id为js的标签会变为div的子标签
/**
* 通过JS创建一个新的节点,实现插入
*/
var newP=document.createElement('p');//创建一个新标签
newP.id='newP';//标签id设为newP
/*newP.id='newP';等价于newP.setAttribute('id','newP');*/
newP.innerText='xiaosi';
list.appendChild(newP);
/**
* 创建一个标签节点
* <script type="text/javascript" src=""></ script>
*/
var myScript=document.createElement('script');
myScript.setAttribute('type','text/javascript');
//list.appendChild(myScript);
/**
* 插入CSS
*/
var myStyle=document.createElement('style');//创建一个空style标签
myStyle.setAttribute('type','text/css');
myStyle.innerText='body{background-color:pink;}';//设置标签内容
document.getElementsByTagName('head')[0].appendChild(myStyle);//不知道head标签下标的话可以先打印看一下
4.2.6 前插
<body>
<p id="js">JavaScript</p>
<div id="list">
<p id="se">JavaSE</p>
<p id="ee">JavaEE</p>
<p id="me">JavaME</p>
</div>
<script>
var ee=document.getElementById('ee');
var js=document.getElementById('js');
var list=document.getElementById('list');
//要包含的节点.insertBefore(newNode,targetNode),新节点插入目标节点前面,他们都包含在list里面
list.insertBefore(js,ee);
</script>
</body>
4.2.7 操作表单
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="#">
<p>
<span>用户名:</span> <input type="text" id="username">
</p>
<!--多选框的值,就是定义好的value-->
<p>
<span>性别:</span>
<input type="radio" name="sex" value="man" id="boy"> 男
<input type="radio" name="sex" value="woman" id="girl"> 女
</p>
</form>
<script>
/**
* 获得提交的信息
*
* */
var
input_text=document.getElementById('username'),
boy_value=document.getElementById('boy'),
girl_value=document.getElementById('girl');
/* //得到输入框的值
input_text.value;
//修改输入框的值
input_text.value = '123';
*/
/* //对于单选框,多选框等固定的值,boy_radio.value只能取到当前的值
boy_value.checked;//查看返回的结果,如果为true,被选中
girl_value.checked=true;//赋值
*/
</script>
</body>
</html>
4.2.8 提交表单
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--MD5工具类-->
<script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js"></script>
</head>
<body>
<form action="#" method="post">
<p>
<span>用户名:</span> <input type="text" id="username" name="username">
</p>
<p>
<span>密码:</span> <input type="password" id="password" name="password">
</p>
<!--绑定事件 onclick 被点击-->
<button type="submit" onclick="aaa()">提交</button>
</form>
<script>
function aaa() {
var uname=document.getElementById('username'),
pwd=document.getElementById('password');
console.log(uname.value);
console.log(pwd.value);
//MD5算法
pwd.value=md5(pwd.value);
console.log(pwd.value);
}
</script>
</body>
</html>
4.2.9 表单绑定提交
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--MD5工具类-->
<script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js"></script>
</head>
<body>
<!--
表单绑定提交事件
οnsubmit=绑定一个提交检测的函数,true false
将这个结果返回给表单,使用onsubmit接受
-->
<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="input-password">
</p>
<input type="hidden" id="md5-password" name="password">//用隐藏的方法你提交的一瞬间密码不会变长
<button type="submit">提交</button>
</form>
<script>
function aaa() {
var uname=document.getElementById('username'),
pwd=document.getElementById('password'),
md5pwd=document.getElementById('md5-password');
console.log(uname.value);
console.log(pwd.value);
//MD5算法
md5pwd.value=md5(pwd.value);
//可以校验判断表单内容,true是通过,false是阻止
return true;
}
</script>
</body>
</html>
5、JQuery简解
5.1 初识JQuery
导入:CDN或者下载到本地,script标签不能自闭和
<!--CDN jQuery 直接从网上粘下来,不需要下载-->
<!-- <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/core.js"></script> -->
<!-- 下载到本地直接导入 -->
<script src="lib/jquery-3.5.1.js"></script>
公式:$(selector).action(),例:
//选择器就是css的选择器
$('#test-jquery').click(function () {
alert('hello jQuery');
});
5.2 选择器
//原生JS,选择器少,麻烦不好记
//标签
document.getElementsByTagName()
//id
document.getElementById()
//类
document.getElementsByClassName()
//Jquery选择器 css中的选择器它都能用,不会的查网站
$('p').click()//标签选择器
$('#id1').click() // id选择器
$('.class1').click() // class选择器
5.3 事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="lib/jquery-3.5.1.js"></script>
<style>
#divMove{
width: 500px;
height: 500px;
border: 1px solid pink;
}
</style>
</head>
<body>
<!--要求:获取鼠标当前的一个坐标-->
mouse:<span id="mouseMove"></span>
<div id="divMove">
在这里移动鼠标试一下
</div>
<script>
//当前网页元素加载完毕之后响应事件,相当于公式的简化
$(function () {
$('#divMove').mousemove(function (e) {
$('#mouseMove').text('x:'+e.pageX+'y:'+e.pageY);
})
});
</script>
<div>
</div>
</body>
</html>
5.4 操作dom元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="lib/jquery-3.5.1.js"></script>
</head>
<body>
<ul id="test-ul">
<li class="js">JavaScript</li>
<li name="python">Python</li>
</ul>
<script>
$('#test-ul li[name=python]').text();//获得ul下面name=python的值
//$('#test-ul li[name=python]').text('aaa');//修改ul下面name=python的值
$('#test-ul').html();//获得ul的html
//$('#test-ul').html('<strong>123</strong>');//修改ul的html
/**
* css的操作
*/
$('#test-ul li[name=python]').css("color","pink");//要设置多个属性可以用键值对$('#test-ul li[name=python]').css({"color","pink"},{})
/**
* 元素的显示和隐藏:本质display:none
*/
$('#test-ul li[name=python]').show();
$('#test-ul li[name=python]').hide();
/**
* 别的用法:可以通过查文档来了解
*/
$(window).width();//只要满足公式,这里是浏览器窗口的宽
</script>
</body>
</html>
6、闭包
概念:一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。
6.1 一个简单的闭包
function A(){
function B(){
console.log(``'Hello Closure!'``);
}
return B;
}
var C = A();
C();// Hello Closure!
函数A的内部函数B被函数A外的一个变量 c 引用。
也就是:
当一个内部函数被其外部函数之外的变量引用时,就形成了一个闭包。
6.2 用途
在 Javascript 中,如果一个对象不再被引用,那么这个对象就会被 GC 回收,否则这个对象一直会保存在内存中
也就是说,A 不会被 GC 回收,会一直保存在内存中。
function A() {
var count = 0;
function B() {
count ++;
console.log(count);
}
return B;
}
var C = A();
C();// 1
C();// 2
C();// 3
count 是函数A 中的一个变量,它的值在函数B 中被改变,函数 B 每执行一次,count 的值就在原来的基础上累加 1 。因此,函数A中的 count 变量会一直保存在内存中。
当我们需要在模块中定义一些变量,并希望这些变量一直保存在内存中但又不会 “污染” 全局的变量时,就可以用闭包来定义这个模块。
6.3 闭包的高级写法
(function (document) {
var viewport;
var obj = {
init: function(id) {
viewport = document.querySelector('#' + id);
},
addChild: function(child) {
viewport.appendChild(child);
},
removeChild: function(child) {
viewport.removeChild(child);
}
}
window.jView = obj;
})(document);
这个组件的作用是:初始化一个容器,然后可以给这个容器添加子容器,也可以移除一个容器。
功能很简单,但这里涉及到了另外一个概念:立即执行函数。 简单了解一下就行,需要重点理解的是这种写法是如何实现闭包功能的。
可以将上面的代码拆分成两部分:(function(){}) 和 () 。
第1个**()** 是一个表达式,而这个表达式本身是一个匿名函数,所以在这个表达式后面加 () 就表示执行这个匿名函数。
因此这段代码执行执行过程可以分解如下:
var f = function(document) {
var viewport;
var obj = {
init: function(id) {
viewport = document.querySelector('#' + id);
},
addChild: function(child) {
viewport.appendChild(child);
},
removeChild: function(child) {
viewport.removeChild(child);
}
}
window.jView = obj;
};
f(document);
在这段代码中似乎看到了闭包的影子,但 f 中没有任何返回值,似乎不具备闭包的条件,注意这句代码:
window.jView = obj;
nction B() {
count ++;
console.log(count);
}
return B;
}
var C = A();
C();// 1
C();// 2
C();// 3
count 是函数A 中的一个变量,它的值在函数B 中被改变,函数 B 每执行一次,count 的值就在原来的基础上累加 1 。因此,函数A中的 count 变量会一直保存在内存中。
当我们需要在模块中定义一些变量,并希望这些变量一直保存在内存中但又不会 “污染” 全局的变量时,就可以用闭包来定义这个模块。
### 6.3 闭包的高级写法
```javascript
(function (document) {
var viewport;
var obj = {
init: function(id) {
viewport = document.querySelector('#' + id);
},
addChild: function(child) {
viewport.appendChild(child);
},
removeChild: function(child) {
viewport.removeChild(child);
}
}
window.jView = obj;
})(document);
这个组件的作用是:初始化一个容器,然后可以给这个容器添加子容器,也可以移除一个容器。
功能很简单,但这里涉及到了另外一个概念:立即执行函数。 简单了解一下就行,需要重点理解的是这种写法是如何实现闭包功能的。
可以将上面的代码拆分成两部分:(function(){}) 和 () 。
第1个**()** 是一个表达式,而这个表达式本身是一个匿名函数,所以在这个表达式后面加 () 就表示执行这个匿名函数。
因此这段代码执行执行过程可以分解如下:
var f = function(document) {
var viewport;
var obj = {
init: function(id) {
viewport = document.querySelector('#' + id);
},
addChild: function(child) {
viewport.appendChild(child);
},
removeChild: function(child) {
viewport.removeChild(child);
}
}
window.jView = obj;
};
f(document);
在这段代码中似乎看到了闭包的影子,但 f 中没有任何返回值,似乎不具备闭包的条件,注意这句代码:
window.jView = obj;
obj 是在函数 f 中定义的一个对象,这个对象中定义了一系列方法, 执行window.jView = obj 就是在 window 全局对象定义了一个变量 jView,并将这个变量指向 obj 对象,即全局变量 jView 引用了 obj . 而 obj 对象中的函数又引用了函数 f 中的变量 viewport ,因此函数 f 中的 viewport 不会被 GC 回收,viewport 会一直保存到内存中,所以这种写法满足了闭包的条件。