一、什么是JavaScript?
是一个流行的脚本语言,java与javaScript没有具体的关系。
ECMAScrip是一个规范。最新版本已经到6版本了。
很多浏览器只停留来es5,开发环境与上线环境不一致。
一切皆为对象。
二、使用
1.引入JS
嵌入式
可以放在head标签或者body
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script> alert("你好");</script>
</head>
<body>
</body>
</html>
链入式
注意
<script src="js/test.js"></script>
<script src="js/test.js"/> //这里不能闭合标签,必须成对出现。要不外链会失效
2.变量
变量的定义
// 定义变量,不可以使用数字开头
var num=1;
// 判断
if (num>=1 && num<2){
alert("hello");
}
浏览器调试
cookie
ES6之后我们对于局部变量使用let
- 转义字符
\' '
\n 换行
\t
- 书写多行 :``
var test=`
dasda
asdasd
`;
- 模板字符串
//另外的作用
let msg=`huang,${name}`
- 字符串长度,以及大小写转换,截取字符串
var str=“ssadas”;
str.length;
str.toUpperCase();
str.toLowerCase();
str.substring(1,2); //包含头不包含尾巴。【) 实例在下图
变量的作用域
局部变量
var 有作用域,在函数体外不可以使用,如果非要使用使用闭包
//内部函数可以使用外部的函数,而外部的函数不能使用内部的
function tess1(){
var a=1;
function test1_1(){
var b=2;
alert(a);
}
alert(b); //func.js:30 Uncaught ReferenceError: b is not defined
}
内外重名,由内向外依次执行
//假设内外重名
function tess1_2(){
var b=1;
function tess1(){
var b=2;
alert('in'+b); //先输出了in 2,再输出了 1
}
tess1();
alert(b);//先输出了in 2,再输出了 1
}
提升变量的作用域
js执行引擎会提升变量的生命,但不会提升赋值
//测试变量作用域
function test3(){
var x;
alert(y);
var y; //弹出的时undefine。对比下不定义。啥都不弹出
}
//测试变量作用域
function test4(){
var x;
alert(y);
}//不报错。但是不会弹出Y;
全局变量
js实际上只有一个全局作用域。
默认全局变量都自动绑定在window对象下
x=1;//不写 ‘use strict’
等价于 window.x;
为了解决这个问题,因为全局变量如果都绑定在window对象下,一定会出问题。
//重新定义全局变量,自己的代码放在自己的全局域中。降低冲突的问题。
var Huang={};
Huang.test="我自动绑定到HUANG上";
window.test1="自动绑定window";
局部作用域
var是函数作用域,let是块作用域。
为了解决 var
function test4(){
var x;
for (var i = 0; i < 3; i++) {
alert(i);
}
alert(i+1);
}
let是块作用域,这里放到for中就不会起作用了。
function test4(){
var x;
for (let i = 0; i < 3; i++) {
alert(i); //func.js:71 Uncaught ReferenceError: i is not defined
}
alert(i+1);
}
const ES6之前,定义常量,约定用大写。
3.数据类型
number
js不区分小数跟整数。
Infinity:表示无限大
字符串
‘a’,“a”
布尔值
true
false
NULL
空
undefined
未定义,在没有定义的情况下。
4.逻辑运算与比较运算
|| 或
&& 且
! 取反
=
==
=== :绝对等于,类型一样,值也一样
NaN,与所有数值都不相同,包括自己。
//可以使用isNaN进行判断
isNaN(NaN);
避免使用浮点数进行运算,存在精度问题。
console.log(1/3===(1-2/3));
Math.abs(1/3 - (1-2/3))<0.0000001
5.数组
JAVA中数组的对象必须相同
var arr=[1,2,3]; //字符串长度
如果出现数组下标越界,就会出现。
1.这里的数组的长度是可变的。空出来的哪些部分出现的是undefine类型
var arr=[1,2,'hello'];
alert(arr.length); //输出3
arr.length=10;
alert(arr.length); //输出10
而在java中
public static void main(String[] args) {
int[] arr=new int[10];
System.out.println(arr.length);
arr.length=11;
}
}
这是有问题的。
2.slice()截取Array的一部分,返回一个新数组。
var arr=[1,2,'hello'];
alert(arr.slice(2,3));//输出hello
3.push,pop,unshift,shift 对数组内弹出压入
arr.push('a'); //压入尾部
arr.pop();//弹出a ,弹出尾部
arr.unshift('a');//压入头部
arr.shift();//弹出尾部
4.sort 排序
arr.sort
5.concat() 链接
arr=[1,2,'hello'];
arr.concat([7,8,9]);
6.join 传出是一个新数组,把原先数组元素的链接起来。
arr.concat([7,8,9]);
alert(arr);//还是输出数组本身的内容
alert( arr.join("+"));//输出 1+2+hello ,但是这是一个新数组
6.对象
以键值对声明属性,以逗号隔开
var student={
name:"xiucai",
age:3,
hobby:['js','java']
};
输出测试:
//如果调用一个没有定义的属性输出的是undefine
student.sex; //输出undefine
//甚至可以动态的添加属性,之前没有性别这个属性
student.sex='男';
… in … js中所有的键都是字符串,值是任意的对象。所以我们在判断某个属性是否在某个对象里边时,实际上是看某个字符串是否在对象中
alert('sex' in student); //输出true
//js本身也具有继承性,
alert('toString' in student);//true
// 是否本身具有此种属性
student.hasOwnProperty(toString);//false
内部对象
标准对象
1.判断对象的类型,使用typeof 关键字
Date
var date1=new Date();
//得到年份
date1.getFullYear();
//得到星期几
date1.getDay();
//获取时间戳
date1.getTime(); //1642668101568
//把时间戳放在对象上返回。
new Date(1642668101568); //返回一个事件对象。
JSON
早期使用xml文件传输文件,ECMAScrip标准下的一种数据交换格式。
- json的格式
- 对象用{}
- 数组用[]
- 所有键值对都是 key:value
可以发现,点对象是可以展开。但是JSON是不可以展开了
//把对象转换为json对象
JSON.stringify(student);
//json转换为对象
JSON.parse('{"name":"胡昂黄","sex":"男"}')
JS与JSON区别
主要是两个格式的问题。
AJax
- 原生js写法
- jQuey封装好的方法
- axios请求
面向对象编程
在java中 类是模板,对象是实例
js中有个原型,可以理解为模板,js所有对象的老祖宗都是Object类。实际上这里特别像是继承,原型就是其父类,只不过这里可以多次继承。为了方便理解,我这里举一个应用实例。
原型
- 首先用java实现
//父类
public class Person {
public String name;
public int age;
public void tell(){
System.out.println(this.name+"TELL");
};
public Person(String name,int age){
this.name=name;
this.age=age;
};
}
//子类
public class Student extends Person{
public Student(String name,int age){
super(name,age);
};
public void studentTask(){
System.out.println("我是一名学生");
}
}
//子类
public class Woker extends Person{
public Woker(String name,int age){
super(name,age);
};
public void wokerTask(){
System.out.println("我是一名工人");
}
}
测试类
public class Test {
public static void main(String[] args) {
Student student = new Student("黄", 19);
Student student1 = new Student("孙孙", 12);
Woker woker = new Woker("吕", 20);
student.tell();
student1.tell();
woker.tell();
student.studentTask();
woker.wokerTask();
}
}
//输出
黄TELL
孙孙TELL
吕TELL
我是一名学生
我是一名工人
以上是java应用场景下的代码,在新建两个同学的时候显然,我们可以使用new Student的方式。直接得到了两个对象。
反观js下,我新建一个同学
var student={
name:黄,
age:19,
tell:function () {
alert(this.name+"tell..")
}
}
如果我紧接着想要吕同学,我没办法像java那样。
var student1={
name:吕,
age:20
//这里我特意空出来去让他继承之前的弹出
};
我想通过js里边的方法,实现对于原先模板student的继承。
var student1={
name:吕,
age:20
//这里我特意空出来去让他继承之前的弹出
};
student1._proto_=student; //输出了吕tell
以上只是一种js新建对象的方法,还有工厂模式,以及构造方法建立
function Person(name,age,family) {
this.name = name;
this.age = age;
this.family = family;
this.say = function(){
alert(this.name);
}
}
//如果想要在其中增加一个方法,需要找到原来的原型,增加。即
Person.prototype.newF=function () {
}
新建类 class ES6之后的。
//定义一个类
class Student{
//构造方法
constructor(name) {
this.name=name;
}
}
//也要使用super实现父类构造器的内容
class Student extends Person{
constructor(name) {
super(name);
}
}
原型链
7.严格检查模式
'use strict';
// 必须写在js的第一行,这样在浏览器中会跳出。
//没有使用 'use strict';之前
i=1;
可以运行而且i是全局变量
'use strict';
i=1;
使用
8. 流程控制
判断:if … if…else if…else
while 循环:while 循环 也一样。
do while 循环
do {
}while ()
for循环
for (let i = 0; i <100 ; i++) {
}
foreach 循环
传一个function进去。
arr.forEach(function (value) {
alert(value);
})
for…in… 循环
i是个索引, in 后边是个数组
var arr=[1,2,'hello'];
for (let i in arr) {
alert(arr[i]);
}
//直接输出i时候是输出下标,但是如果此时执行arr.index="123"; 他会输出 1,2,3,index
arr.index="123"; //输出1,2,3,index
//正确写法 for of 在循环数组时有点区别,不用像上边一样用数组加下标,而是采用这种方法实现。直接输出number即可。
for (const number of arr) {
alert(number);
}
//在使用
for (const number of arr) {
alert(arr[number]);//输出的是 2 ,hello
}
//使用
for (const number of arr) {
alert(arr[number-1]);//又发现输出不了hello,number应该返回的是数组的对象,而in是返回的数组下标
}
for…of… 循环
var set=new Set([3,1,1,1,1]); //set可以去重
jsfor (const number in set) {
alert(number);//无任何输出
}
// 只有of能遍历 set跟Map
for (const number of set) {
alert(number);
}
9.Map和Set es6之后出来的
应用场景:对应学生的名字和学生的成绩。
Map
var map=new Map([['top',100],['all',90]]);
//取值get
alert(map.get('top'));
看准[‘top’,100],[‘all’,90],需要在前边加个括号
map.set(map.set("mm",9));
alert(map.get('mm')); //输出9
Set
var set=new Set([3,1,1,1,1]); //set可以去重
set.add(2);//增加
set.delete(1);//删除
set.has(1); //判断set里边是否有某个元素
10.函数
对象里边有方法,但是函数在js中即可
定义
function abs(x) {
if (x>=0){
return x;
}else
return -x;
}
//定义二 采用匿名内部类
var abs=function(x) {
if (x>=0){
return x;
}else
return -x;
}
测试调用
不传参数
手动抛出异常
'user strict';
//typeof x !=='number' 重要。返回的是一个字符串
//当为空时
function abs(x) {
if (typeof x !=='number'){
throw 'Dont NUll';
}
if (x>=0){
return x;
}else
return -x;
}
arguments, 代表参数传递进方法的所有参数。想要保持参数唯一
if (arguments.length>2)
{
throw 'Dont More';
}
rest 获取除了传入进去的参数以外的所有参数。 …rest 要定义在参数最后
function test(a,v,...rest){
alert(rest);
}
方法
方法的定义
var person ={
name:"hhh",
birthday:2000,
age:function (){
var time=new Date().getFullYear();
return time-this.birthday;
}
};
//在浏览器中调用:person.age()
function getage(){
var time=new Date().getFullYear();
//注意这里的this与上方的this,这里的this指的是当前的对象,所以这里是报NaN
return time-this.birthday;
}
var person ={
name:"hhh",
birthday:2000,
age:getage
};
//调用 person.age();
apply ,所有方法都有这个参数。用来指定一个对象。
为了解决上边所说的getage发方法中,this指代不明
function getage(){
var time=new Date().getFullYear();
return time-this.birthday;
}
var person ={
name:"hhh",
birthday:2000,
age:getage
};
//第一个参数指的是对象,第二个参数可以传入空
getage.apply(person,[]);
11.操作对象 BOM
1.window对象 代表全局对象
2.navigator ,小写 大部分时间不使用判断,因为可以被人为修改。这就是可以能电脑和手机改的。怕被撸羊毛
navigator.appName
navigator.appVersion
3.screen 代表屏幕的尺寸
4.location 代表当前页面的URL信息
href:当前指向的对象
location.reload() //重载
location.assign('https://www.baidu.com/') //可以重定向到另外一个地方,跳转到这个页面上
5.document 代表当前的页面,HTML,DOM文档树
document.getElementById()
document.cookie //可以获取cookie
可以获取具体的文档树节点。
cookie有可能被劫持。服务器端可以设置httpOnly保证安全
6.history
浏览器的七块
history.back()
history.forward()
12.操作对象DOM
1.获取节点
<h1>我的第一个html</h1>
<div id="father">
<p id="test1">111</p>
<p class="test">111</p>
</div>
<script>
document.getElementById('test1');
document.getElementsByClassName('test');
document.getElementsByTagName('h1');
//值得注意的是必须是getid 才能实现.child,用classname 不能实现
var child=document.getElementById('father').children;
</script>
2.更新节点
var test1=document.getElementById('test1');
//修改节点里的文本内容
test1.innerText="123"
//解析html的内容,比如说<strong>
test1.innerHTML='<h1>121</h1>' //在html页面上对test1的节点文本内容也变化了.
//变换样式 操作css
test1.style.color=red
3.删除节点
删除节点,要找到父节点,不能自己删除自己
<h1>我的第一个html</h1>
<div id="father">
<p id="test1">111</p>
<p class="test">111</p>
</div>
现在想要删除test1.
var test1=document.getElementById('test1');
var father=test1.parentElement
father.removeChild(test1)
删除是一个动态的过程,删除多个节点的时候,children是在动态变化的.删除节点时一定要注意.
//这种方式是动态的删除的,就比如说这个节点删除完事以后,再删除下一个节点.
father.removeChild(father.children[0])
father.removeChild(father.children[1])
4.插入节点
获得了某个dom节点.可以通过innerHTML可以增加元素,但是如果里边有一些内容的时候,会产生覆盖.不推荐.
追加 对象.appendchild(js) ,放已存在的节点
var father=document.getElementById('father')
var wantAdd=document.getElementById('test1')
father.appendChild(wantAdd)
使用了放在内部,首先要有这样一个节点.test1.
放置新的节点
//创建一个新的节点,这里创建一个p标签
var new_p=document.createElement('p');
new_p.id='newp';
new_p.innerText='插入';
//插入块
var father=document.getElementById('father')
//father.appendChild(new_p); 这是在father后边的子节点插入
var wantAdd=document.getElementById('test1');
wantAdd.append(new_p); //这是在之后插入
最初:
在父节点下插入:father.appendChild(new_p);
在子节点下插入:wantAdd.append(new_p); //这是在之后插入
newScript.setAttribute(‘type’,‘text/css’); 主要是这个用法.比上边的对象.id更泛化
//万能写法
//新建一个节点,标签名字叫做style
var newScript=document.createElement('style');
//设置styple的属性 text/css
newScript.setAttribute('type','text/css');
//像这个标签内加入内容,即css内容
newScript.innerHTML='body{background-color: #a43535;}';
//值得注意的是取得head标签以后这里是对象里边的第一个
var head=document.getElementsByTagName('head')[0];
head.appendChild(newScript);
insert 插入 任意对象.insertBefore(A,B),在A的节点在B的节点
13.操作表单
在本地进行一些验证的功能,本身form标签也是DOM标签下的一个节点
- 密码框
- 文本框 text
- 下拉框 select
- 单选框 radio
- 多选框 checkbox
//先获取对象
var input_username=document.getElementById('username');
//然后根据这个对象的一些属性进行观察 比如说
input_username.value
实现表单提交 这里有些问题
<!--表单提交 需要onsubmit,想要拦截一个表单,使用onsubmit即可.-->
<form action="https://www.baidu.com" method="post" onsubmit="return submitMethod()">
<p>用户名:<input type="text" id="username" name="" required></p>
<!-- 没有name属性浏览器不会抓到爆-->
<p>密码:<input type="password" id="password" name="" required></p>
<!-- 这个按钮被提交的时候绑定个事件-->
<button type="submit">提交</button>
</form>
<script>
function submitMethod() {
alert('1');
var username=document.getElementById('username');
var passwork=document.getElementById('password');
console.log(username.value);
console.log(password.value);
//在这里修改拿到的对象的值,传上去的就会知道了.
// password.value=md5(passwork.value);
// 应用场景,校验判断表单内容.如果在这里就会问题,就不会产生提交表单的情况,当然要把 <button οnclick="submitMethod()">提交</button> 里边的去掉
return true;
}
</script>
三.JQuery
封装了大量js方法的库,里边存在大量的js函数
学习网址:https://jquery.cuishifeng.cn/
1.下载获取
官网下载
https://jquery.com/download/
使用CDN jQuery
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
2.语法与选择器
语法:$(selector).action()
<script>
//里边是选择器
$('#test_jquery').click(function () {
alert('hello');
})
</script>
选择器
$('#test_jquery') //id
$('.test_jquery') //类
事件 actions
- 鼠标事件
- 键盘事件
- 其他事件
$(function () {
})//等同于
$(document).readable(function () {
})
3.操作Dom
//原先
var test1=document.getElementById('test1');
//修改节点里的文本内容
test1.innerText="123"
//用了js之后
$('.before').text('更改后的内容');