JavaScript
狂神有一些地方笔记写的不对,我跟着敲得时候有一些自己改了过来,但是不能保证写出的代码就是对的//
有不懂的地方问百度//
在网页里调试js
在网页中预览了代码之后,右键然后选择审查(谷歌浏览器),然后选择colsole控制台来进行调试
控制台常用代码:
console.log() //打印代码中的变量
也可以选择sources可以看到源代码,通过打断点来进行调试。
Application用来查看cookie
Element用来查看网站元素
network用来抓包
在HTML中使用js
<!-- HTML中内部引入script 标签中写javascript代码 -->
<!-- script标签必须成对出现 不能使用自闭和来偷懒-->
<!--弹出窗口显示helloword -->
<script>
//js的语法中,注释是双斜杠 还有语句后要加上分号
alert("hello,word");
</script>
<!--外部引入的话 需要在标签中加入属性src 指向写好的 .js 文件-->
<script src="js/lesson1.js"></script>
语法
<script>
// 全局自定义变量统一使用var 如同c++ 里面的auto
// 局部自定义使用let 前提支持SE6语法 (let 是用来取代var的)
var c=1;
var name="ssss";
// 如果使用条件判断, 就像java使用[if] [else if]就行
if(9>c){
alert(name);
}
</script>
数据类型快速浏览
js不区分整数和小数
== 等于 (类型不一样,值一样,也会判断为true)
=== 绝对等于 (类型一,值一样,才会判断为true)
所以平时我们要坚持使用绝对等于。
NaN 表示不是一个数 not a number
Infinity 无限大
注意精度问题:
alert( (1/3) === (1-2/3) );//返回false
alert((1/3)-(1- 2/3)<0.000001)//返回true
注意空和未定义不一样
null:定义了但是没有值
undefined:未定义 查询数组越界也会出现undefined
数组:类似python里的列表 因为var类似auto 使用中括号括起来
var arr =[1,2,3,true,null,'s'];//尽量使用这种方式 保证可读性
new Array(1,12,3,5,'hello');//这种方式创建数组也行
对象:使用大括号括起来
//属性之间使用逗号隔开 类似于结构体
var Person = {
name='szg',
age=4,
tag=['student',3,6];
};
严格检查模式
在js代码前面加入这句话能够规避一些不严谨的操作定义
'use strict';
数据类型
字符串
- 正常字符串使用单引号或者双引号包裹
- 注意转义字符 \
\' // 代表单引号
\n // 代表换行
\t // 代表table
\u4e2d // 输出汉字‘中’ unicode字符 格式\u####
\x41 // ascii字符
- 多行字符串编写
//使用反引号来多行字符串
var=` ss
name
`
- 模板字符串
'use strict';
let name='szg';
//类似el表达式 合并字符串
let msg=`你好呀,${name}`;
console.log(msg);
- 其他知识
//通过length获得长度
name.length;
//通过toUpperCase()来将字母全部转为大写
name.toUpperCase();
name.toLowerCase();
//注意字符串是不可变的 不能通过下标修改字符串里的字符
name.indexOf('s');//获得s在字符串中的下标
name.substring(1,3)//前闭后开
数组
Array可以包括任意类型的元素
- 数组属性
//数组长度直接可以通过length修改 如果长度太小,多余的元素会被舍弃
arr.length=2;
//可以直接通过下标赋值
arr[1]=1;
//可以通过indexof(值)来获得该值下标
arr.indexof(1);//获得数字的一的下标
arr.indexof("1");//获得字符串形式的一的下标
//slice 数字版的substr 可以截取一部分,返回一个新数组
arr.slice(1,2);
arr.push('a','b');// 压入了两个字符
arr.pop();//弹出尾部元素
arr.shift();//弹出头部元素
arr.unshift('a','b');// 压入头部元素 按照括号内元素的顺序(第一个是a 第二个是b
arr.sort()// 排序
arr.reverse(); //字符串反转
arr1.concat(arr2);//字符串拼接
arr1.concat([3,4,5]);
arr.join('-');// 打印数组,通过 - (连接符)连接每个元素
//多维数组
arr=[[1,2]['1','2','3']];
arr.fill(); // 数组填充
对象
var 对象名 = {
属性名:属性值,
属性名:属性值,
属性名:属性值 //最后一个属性值不需要加逗号
}
- 当想要获取对象中不存在的属性时,会提示未定义而不是报错
- 可以动态的删减添加属性
//在控制台输入 delete +对象名.属性名 即可删除属性
delete Person.name;
// 在控制台输入 对象名.属性名 = 属性值 即可添加属性
Person.haha="haha";
- 判断属性是否在这个对象中
// 属性名 + in + 对象名
'age' in Person
//可以通过继承反向找到父类的方法
‘toString’ in Person
// 返回true说明存在 ,但是我们没有在对象中设置这个属性,说明默认的继承了父类
- 判断属性是否是这个对象自身拥有
Person.hasOwnProperty('age')//返回true
Person.hasOwnProperty('toString')//返回false
分支和循环
if,else,while,dowhile都和java一样
for in 由于历史遗留问题,它遍历的实际上是对象的属性名称。一个Array数组实际上也是一个对象,它的每个元素的索引被视为一个属性。当我们手动给Array对象添加了额外的属性后,遍历时会将额外的属性也加入进来
let age=[1,2,3,4,5,6,7,4,3];
// 当然,可以使用for in
for(let num in age){// num是下标
if(age.hasOwnProperty(num)){
console.log('存在');
console.log(age[num]);
}
}
// for of 是遍历的集合本身的元素,比forin更加完善
for(let x of age){
console.log(x);
}
// 也可以使用 forEach 函数
age.forEach(function(value){
console.log(value);
});
Map和Set
// 基本使用方法:
var map =new Map([ ['tom',10],['javk',90],['szg',100] ]);
var name=map.get('szg');// 通过key获得value
map.set('admin',23);// 加入map
map.delete('tom'); // 删除
console.log(name);
//set是一个无序不重复的集合
var set=new Set([1,3,2,5,4,6,7,2,3,4]);
console.log(set.has(1));
set.delete(1);
set.add(9);
// 遍历
for (var x of set){
console.log(x);
}
for (var x of map){//x是一个二元数组Array
console.log(x);
}
函数
- 定义函数
// 方法一:后端习惯
function abs(x){
if(x>=0)return x;
else return -x;
}
// 方法二:前端习惯 (有点像匿名内部类
var abs=function(x){
if(x>=0)return x;
else return -x;
}
// 两种方法的调用方法是一样的
abs(10);
javascript可以传任何个参数,也可以不传参数
参数进来是否存在的问题?假设不存在参数,如何抛出异常?
var abs = function(x){
//手动抛出异常来判断
if (typeof x !== 'number') {
throw 'not a number';
}
if (x>=o) {
return x;
}else{
return -x;
}
}
-
arguments对象:
加入函数的实参没有写多个,但使用时传入了多个参数,使用arguments对象可以把这多个参数用数组返回,argument对象其实就是传入的所有参数的数组。
特性:- arguments对象和Function是分不开的。
- 因为arguments这个对象不能显式创建。
- arguments对象只有函数开始时才可用。
使用方法:
虽然arguments对象并不是一个数组,但是访问单个参数的方式与访问数组元素的方式相同,直接采用读取下标
因此在js代码中,不需要指出参数名称,就能够访问他们
//有点类似于java的 args 吧。。。
function test() {
var s = "";
for (let i = 0; i < arguments.length; i++) {//在foe内部尽量使用let而不i是var
console.log(arguments[i]);
}
}
test("name", "age");
- rest函数
使用场景:函数定义了两个参数,但是传入了第三个参数,要怎么取出第三个参数呢?
// 以前使用 arguments的 方法
function test (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]);//如果有重复元素会只显示一个同时标清重复了几次
}
}
}
//现在的方法(rest参数):在函数中定义rest参数
function test1(a,b,...rest){
console.log('a->'+a);
console.log('b->'+b);
console.log(rest);//以数组的形式输出
}
变量的作用域
-
内部函数可以访问外部函数的成员,反之不行
-
在客户端 JavaScript 中,Window 对象是全局对象,所有的表达式都在当前的环境中计算。 也就是说,要引用当前窗口根本不需要特殊的语法,可以把那个窗口的属性作为全局变量来使用。
-
ES6中的let关键字,用于解决局部作用域冲突问题,应该用let去定义局部变量而不是var
-
在ES6之前,定义常量使用全部大写字母命名的变量就是常量,而现在使用const定义常量
方法
定义方法:方法(method)是通过对象调用的javascript函数。也就是说,方法也是函数,只是比较特殊的函数
var person = {
name: 'zhang',
brith: 1997,
//方法
age: function(){
var now = new Date().getFullYear();
return now - this.brith; //this是默认指向调用它的那个对象,这里值person
}
}
//如果想调用属性: person.name;
//如果想调用方法: person.age();
问题:为啥我的一直说person未定义,明明已经定义好了??
因为你把中间的逗号写成了分号。。。
//
function getAge(){
var now = new Date().getFullYear();
return now - this.brith; //this是默认指向调用它的那个对象,这里值person
}
var person = {
name: 'zhang',
brith: 1997,
//方法
age: getAge
}
//调用方法有两种方式 。两种方式执行结果相同
//一个是直接调用
person.getAge();
//一个是使用apply,改变了this的指向
//括号中第一个是对象名称 第二个是内部参数,因为不需要参数,所以只写一个中括号
getAge.apply(person,[]);
对象
标准对象列举
// 使用 typeof 关键字来获取所想想到的数据类型
typeof 123 //number
“number”
typeof ‘123’// string
‘string’
typeof true// boolean
“boolean”
typeof NaN //number
“number”
typeof [] //object
typeof {} //object
typeof Math. abs // function
typeof undefined // ??underfined类型
Date对象
列举的一些和java类似
var now = new Date();
now. getFu11YearO); //年
now. getMonth(); //月 要注意往前推了一个月!!!
now. getDate(); //日
now. getDay(); //星期几
now. getHours(); //时
now. getMinutes(); //分
now. getseconds(); //秒
now. getTimeO); //时间戳全世界统一1970 1.1 0:00:00 毫秒数
比较复杂的函数
toLocaleSting:
- 本地时间把 Date 对象转换为本地格字符串。
- 可把一个 Number 对象转换为本地格字符串。
- 可把一个 Array 对象转换为本地字符串。
JSON对象
目前几乎已经成为了轻量级传递信息的一种格式标准
格式:
- 对象都用{}
- 数组都用[]
- 键值对都用 key:value
//一个简单对象
var user={
name :'szg',
age :3,
sex:'男'
}
//将对象转化为一条json格式的字符串
//结果: '{"name":"szg","age":3,"sex":"男"}'
var jsonuser=JSON.stringify(user);
//将一条json格式的字符串转化为一个对象
var User=JSON.parse(jsonuser);
// 参数为字符串时,如果字符串内部使用的是双引号,则大括号外面要使用单引号
var User=JSON.parse('{"name":"szg","age":3,"sex":"男"}');
继承
原型继承
var student = {
name : 'szg',
age:3,
run: function (){
console.log(this.name + "run ... ");
}
}
var xiaoming = {
name : 'xiaoming'
}
//利用原型继承 _proto_ 有点类似于指定父类,小明可以实现用student的参数
//可以随意更改指向,过于随便有点反人类
xiaoming.__proto__ = student;
xiaoming.run();//小明就跑起来了
console.log(xiaoming.run());
class继承
// class 关键字是在ES6引入的 和java一样
class student{//定义一个学生类
constructor(name) {
this.name=name;
}
hello (){
alert('hello');
}
}
var xiaoming=new student("xiaoming");
xiaoming.hello();
class xiaostudent extends student{
constructor(name,grade) {
super(name);
this.grade=grade;
}
}
var xiaohong=new xiaostudent("xiaohong",3);
但是通过打印小红可以看到其本质还是通过 proto 指定student为其父类
当在控制台打印上面的小红之后,可以发现每次拓展 proto会到最底端的object然后继续拓展会发现形成了一个圈。叫做原型链(具体百度
操作BOM对象
- window 当前窗口的信息 (长、宽
- navigator 当前浏览器的信息 (版号、所用系统
- screen 当前屏幕的信息 (长、宽
- location 当前页面的URL信息 (地址、连接、协议等
- document 当前页面的代码信息 (页面标题、获得节点、网页cookie、
扯皮:关于cookie的劫持的例子:登陆淘宝,天猫也会自动登录,因为cookie被淘宝发给了天猫)
- history 代表浏览器的历史记录,可以操控页面的前进或者后退( .back() 和 .forward() )
操作DOM对象
浏览器网页就是一个DOM树形结构
ID不要随手敲一个空格上去 空格也会算在id的一部分
获得DOM节点
<div id="father">
<h1> 标题1 </h1>
<p id ="p1">p1 </p>
<p class ="p2">p2 </p>
</div>
<script>
//注意通过ID得到的函数的名称中间是Element 而通过 名称和类 的函数中间是 Elements
var h1 = document.getElementsByTagName('h1'); //根据标签名称
var pl = document.getElementById('p1'); //根据标签id
var p2 = document.getElementsByClassName('p2'); //根据标签的class
var father = document.getElementById('father');
var childrens = father.children; //获取父节点下的所有子节点
var first_child = father.firstchild
var last_child = father.lastchild
</script>
更新DOM节点
<div id="id1">123 </div>
<script>
//利用js改变页面上的内容
var id1=document.getElementById("id1");
id1.innerText="456";//修改文本内容
id1.innerHTML='<strong> 456 </strong>'//修改格式为加粗
id1.style.color='red';// 变红
id1.style.fontsize='20px';// 变大
</script>
删除DOM节点
<div id="id1">123
<h1>h1</h1>
<p id='p1'>p1</p>
<p class ='p2'>p2</p>
</div>
<script>
// 删除p1的步骤
// 获得父节点然后删除子节点
var self=document.getElementById("p1");
var father=p1.parentElement;
father.removeChild(self);
</script>
注意删除多个节点,要从后往前删 例如:
//下面的删除方法是不对的 因为删除了第一个子节点之后,后面的子节点都往前挪了一个
father.removeChild(father.children[0]);
father.removeChild(father.children[1]);
father.removeChild(father.children[2]);
//所以应该为从后往前删
插入DOM节点
我们获得了某个Dom节点,假设这个dom节点是空的,我们通过 innerHTML 就可以增加一个元素了,但是这个Dom节点已经存在元素了,我们就不能这么干了!会产生覆盖
<p id="js"> javascript</p>
<div id="list">
<p id="ee">javaee</p>
<p id="se">javase</p>
<p id="me">javame</p>
</div>
<script>
var me = document.getElementById('me');
var js = document.getElementById('js');
var list = document.getElementById('list');
list.appendChild(js);//appendChild 是插入到后面
//要包含的节点.insertBefore(newNode,targetNode)
//me是在list里面 也就是把在list外面的js插入到me之前
list.insertBefore(js,me);
//创建新的标签后记得设置其格式
//创建一个节点(HTML)
var newP = document.createElement('p');//创建一个p标签
//newP.setAttribute('id','newP'); 与下面的直接设置等同效果
newP.id = 'newP';
newP.innerText = 'Hello,Kuangshen';//设置文本内容
//创建一个节点(JS)
var myScript = document.createElement('script');
myScript.setAttribute('type','text/javascript');
//创建一个style标签(CSS)
var myStyle = document.createElement('style');//创建了一个空style标签
myStyle.setAttribute('type','text/css');
myStyle.innerHTML = 'body{background-color:red;}';//设置标签内容
//放在head里面,放回的是数组类型,但是只有一个元素,所以取第0号
//将新标签(css)插入到 head的子节点的后面
document.getElementsByTagName('head')[0].appendChild(myStyle);
</script>
获取表单
<body>
<form action='#' method="post" >
<p>
<span>用户名:</span> <!--一个行内文本元素 -->
<input type="text" id="username">
</p>
<p>
<span>性别</span>
<input type="radio" name="sex" value="man" id="boy">男
<input type="radio" name="sex" value="women" id="girl">女
</p>
</form>
<script>
var input_text = document.getElementById('username');//得到整个文本框标签
//得到文本框的值
var itext=input_text.value;
//修改文本框的值
input_text.value='szg';
var boy_radio = document.getElementById('boy');
var girl_radio = document.getElementById('girl');
//对于单选框、多选课等固定的value,boy_radio.value只能去到当前的值
//看返回的结果,是否为true,如果为true则被选中
if(boy_radio.checked==false && girl_radio.checked==false)
{
alert("未选择");
boy_radio.checked=true;
}
</script>
</body>
扩展加密表单
对表单提交的密码进行加密,利用MD5在控制台加密
<!-- 记得导入工具包-->
<head> <script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js"></script>
</head>
<body>
<form action="https://www.baidu.com" 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被点击。按钮提交事件aaa()--> .
<button type="submit" onclick="aaa()">提交</button>
</form>
<script>
function aaa() {
var pwd = document.getElementById('password');console.log(pwd.value);
//MD5算法将其变成乱码,一段字符串加密之后的密文是固定的,因此可以通过对比已知密文“破解”,但是实际上该加密是不可破解的。
pwd.value = md5(pwd.value);
console.log(pwd.value);
}
</script>
</body>
这样子会造成一定程度的感观不好,因为提交的一瞬间,用户会发现自己的密码框里的密码会变得特别长。
优化表单加密方式
<!-- 记得导入工具包-->
<head> <script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js"></script>
</head>
<body>
<!-- 使用表单提交优化
οnsubmit= return + 检测的函数,返回true或false-->
<form action="https://www.baidu.com/" method="post" onsubmit="return check()">
<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 check() {
var pwd = document.getElementById("input-password" );
//通过隐藏的框去提交 这样就不会该改变密码框的内容而影响感官了
var md5pwd = document.getElementById('md5-password' );
md5pwd.value = md5(pwd.value);
//此处可以加入判断表单的内容是否符合要求 ,如是否有英文,是否有特殊字符等等。
//如果满足要求返回true即可提交
return true;
}
</script>
</body>
jQuery
获取
有两种方式:一个是在官网下载然后在本地引入,第二个是现在练习可以使用cdn的工具连接直接写在head中
- 下载那个开发版就可以了,然后导入到项目中.
<head><script src="lib/jquery.js"></script></head>
- 在cdn上寻找
<head><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script></head>
使用
唯一公式:
$(selector).action()
简单使用:
<a href="" id="jq_test1">点我</a>
<script type="text/javascript">
$('#jq_test1').click(function(){//css选择 id对应 #
alert('hello,jQuery');
})
</script>
选择器:
<!-- 首先css的选择器都能够使用 示例如下-->
$('p').click() <!-- 标签选择-->
$('#id').click() <!-- id选择-->
$('.class').click() <!-- class选择-->
然后可以通过查询文档了解更多的选择器:jQuery API 中文文档 | jQuery API 中文在线手册 | jquery api 下载 | jquery api chm (cuishifeng.cn)
事件
可以参考上面文档,有键盘鼠标的相关操作、点击、元素改变、焦点等等。。。
示例实现了一个窗口,鼠标在里面可以实时反应鼠标的坐标
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<style>
#divMove{
width:500px;
height:500px;
border:1px solid red;
}
</style>
</head>
<body>
mouse:<span id = "mouseMove"></span>
<div id = "divMove">
在这里移动鼠标试试
</div>
<script>
//当网页元素加载完毕之后,响应事件
//$(document).ready(function(){}) 化简为下面一句话
$(function(){
$('#divMove').mousemove(function(e){
$('#mouseMove').text('x:'+e.pageX+"y:"+e.pageY)
})
});
</script>
</body>
</html>
操作DOM
<ul id ='test-ul'>
<li class ='js'> js</li>
<li name='python'> python</li>
</ul>
<script>
//以下效果自己选择
//var jstext= $('#test-ul li[name=python]').text();//获得li子结点中name为python的元素的文本值
//$('#test-ul li[name=python]').text('new py');//设置为一个新的值
//$('#test-ul li[name=python]').css({"color":"red"}); //通过css修改格式 花括号中间可以放多个键值对然后逗号隔开
//$('#test-ul li[name=python]').hide(); //隐藏该标签
//$('#test-ul li[name=python]').show(); //显示该标签
//var httext= $('#test-ul').html();//获得 html 格式
//$('#test-ul').html('<strong>123</strong>');//覆盖了整个ul标签改为了 加粗的123
</script>