JavaScirpt总结
JavaScirpt
JavaScript(简称“JS”) 是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。JavaScript 基于原型编程、多范式的动态脚本语言,并且支持面向对象、命令式和声明式(如函数式编程)风格。
注意事项:标注尽量使用// xxxx //后面加个空格
函数定义:定义变量 变量类型 变量=变量值
例如:var sum = 1;
console.log();
//相当于JAVA中的System.out.print(); 打印信息到控制台
数据类型(简略说明)
变量
var a = 1
number js不区分小数和整数
var num = 1;
123 // 整数
123.1 // 浮点型
1.123e3 // 科学计数法
-99 // 负数
NaN // not a number
Infinity // 表示无限大
字符串
'abc'
"abc"
布尔值
true
false
逻辑运算
&& 两个为真,结果为真
|| 一个为真,结果为真
! 真就是假,假的就是真
比较运算符 对js来说不要使用== 作为比较 用===作为比较
=
== // 等于(类型不一样,值一样,也会判断为true)
=== // 绝对等于(类型一样,值一样,才会判断为true)
- NaN===NaN, NaN与所有的数值都不相等,包括自己
- 只能通过isNaN(NaN)来判断
尽量避免使用浮点数来进行运算,会有浮点数损失
数组
Java的数组必须是相同类型的对象,js中不需要
//为保证代码的可读性,尽量使用[]
var arr = [1,2,3,4,'hello',null,true];
new Array(1,22,3,'hello');
取数组下标如果越界了不会报错,会报undefined
null 和 undefined
- null 空
- undefined 未定义
对象
对象使用的是{}
,数组使用的是[]
,每个属性要用,
隔开,最后一个不需要
// 相当于JAVA中的Person person = new Person()
var person={ //name,age,tags为属性字段
name: "hdt",
age: 3,
tags: ['js','hy','web']
}
控制台取对象的值
person.name
"hdt"
person.tags
(3) ["js", "hy", "web"]
person.age
3
严格检查模式 ES6新特性
严格检查模式,可以预防JavaScript的随意性导致产生的一些问题
<script>
// IDEA需要设置支持ES6语法
// 'use strict'; 严格检查模式,预防javascript的随意性导致产生的一些问题
// 必须写在javascript的第一行。
// 局部变量建议都使用let去定义,var是全局变量
'use strict';
let i = 1; // let为局部变量
var b = 2; // var为全局变量
</script>
数据类型(详细解析)
字符串
1、正常字符串我们使用' '
和" "
包裹
2、注意转义字符\
(重要)
//严格检查模式
'use strict';
console.log("a");
console.log('b');
console.log("\'");
"\'" // '
"\n" // 换行
"\t" // 大空格
"u4e2d" // Unicode字符
"x41" // Ascll字符
3、多行字符串编写 ES6 (重要)
let ms = `hello
wo
java
`
4、模板字符串 ES6 (重要)
// name->name
let name = "hdt";
let age = 2;
let smg = `你好,${name}`
5、字符串长度 ES6
let stu = "heidaotu";
console.log(stu.length); // 打印长度
console.log((stu[0])); // 打印数组中第一个数值
6、字符串不可变 (重要)
7、大小写转换
// 这里是方法不是属性
console.log(stu.toUpperCase())
-> HEIDAOTU
console.log(stu.toLowerCase())
-> heidaotu
8、获取元素第一次出现的位置
console.log(stu.indexOf('d'))
-> 3
9、截取第一个元素到元素 (重要)
// [1,3)
console.log(stu.substring(1,3))
-> ei
// 从第一个字符串到最后
console.log(stu.substring(1))
-> eidaotu
数组
Array可以包含任意的类型数据
let arr = [1,2,3,4,5,6];
1、长度
加入arr.length赋值,数组大小会发生变化
arr.length=10
-> 10
console.log(arr)
-> (10) [1, 2, 3, 4, 5, 6, 空 ×4]
2、indexOf,通过元素获得下标索引
var arrs = [1,2,3,4,'1','2',"2"]
-> undefined
arrs.indexOf(2)
-> 1
arrs.indexOf('2')
-> 5
arrs.indexOf("2")
-> 5
字符串的'1',"1"和数字1是不同的
3、slice() 截取Array的一部分,返回一个新数组,和java的substring类似 (重点)
var arrs = [1,2,3,4,'1','2',"2"]
-> undefined
arrs.slice(1)
-> (6) [2, 3, 4, "1", "2", "2"]
arrs.slice(1,3)
-> (2) [2, 3]
4、push(),pop() 尾部
arrs
-> (8) [1, 2, 3, 4, "1", "2", "2", "a"]
arrs.push('b','c') // push()为压入到尾部
-> 10
arrs
-> (10) [1, 2, 3, 4, "1", "2", "2", "a", "b", "c"]
arrs.pop() // pop()为弹出尾部元素
-> "c"
arrs
-> (9) [1, 2, 3, 4, "1", "2", "2", "a", "b"]
5、unshift(),shift() 头部
arrs
-> (9) [1, 2, 3, 4, "1", "2", "2", "a", "b"]
arrs.unshift('a','b') // unshift()为压入到头部
-> 11
arrs
-> (11) ["a", "b", 1, 2, 3, 4, "1", "2", "2", "a", "b"]
arrs.shift() // shift()为弹出头部元素
-> "a"
arrs
-> (10) ["b", 1, 2, 3, 4, "1", "2", "2", "a", "b"]
6、排序 sort() 元素反转reverse()
arr
-> (3) ["B", "A", "C"]
arr.sort() // 排序
-> (3) ["A", "B", "C"]
arr.reverse() // 元素反转
-> (3) ["C", "B", "A"]
7、拼接concat()
arr
-> (3) ["C", "B", "A"]
arr.concat("D","E",1)
-> (6) ["C", "B", "A", "D", "E", 1]
arr
-> (3) ["C", "B", "A"]
concat() 并没有修改数组,只是返回一个新的数组
8、连接符join()
打印拼接数组,使用特定字符串连接
arr
(3) ["C", "B", "A"]
arr.join("-")
"C-B-A"
9、多维数组
let arr = [[1,2],[3,4],["5","6"]];
arr
(3) [Array(2), Array(2), Array(2)]0: (2) [1, 2]1: (2) [3, 4]2: (2) ["5", "6"]length: 3__proto__: Array(0)
arr[1][1]
4
对象
键值对
var 对象名 = {
属性名: 属性值,
属性名: 属性值,
属性名: 属性值
}
// 定义了一个person对象,它有4个属性
var person = {
name: "hdt",
age: 22,
email: "402@qq.com",
score: 99
}
js中对象,{...}表示一个对象,键值对描述属性 XXX:XXX,多个属性用逗号隔开,最后一个不需要加逗号
JavaScript中的所有键都是字符串,值是任意对象
1、对象赋值
person.name = "hdttt"
"hdttt"
person.name
"hdttt"
2、使用一个不存在的对象属性,不会报错,提示urdefined
person.toto
undefined
3、动态的删减属性,通过delete删除对象的属性
person
{name: "hdttt", age: 22, email: "402@qq.com", score: 99}
delete person.name
true
person
{age: 22, email: "402@qq.com", score: 99}
4、动态的添加,直接添加新属性即可
person
{age: 22, email: "402@qq.com", score: 99}
person.from="大草原"
"大草原"
person
{age: 22, email: "402@qq.com", score: 99, from: "大草原"}
5、判断属性值是否存在这个对象中 xxx in xxx
'age' in person
true
//继承
'toString' in person
true
6、判断一个属性是否是这个对象自身拥有的hasOwnProperty()
person.hasOwnProperty('age')
true
person.hasOwnProperty('toString')
false
流程控制
if判断
let sum = 1;
if (sum>0){
console.log("大于");
}else {
console.log("小于");
}
while循环,避免死循环
let sum = 1;
while (sum<50){
sum++;
console.log(sum)
}
do{
sum++;
console.log(sum)
}while (sum<50)
for循环
let sum = 1;
for (let i = 0; i < 20; i++) {
console.log(i)
}
foreach循环
let a = [1,2,66,9,3];
a.forEach(function (e){ // 对函数方法进行循环
console.log(e);
})
for in 循环,类似于java中的foreach循环
let a = [1,2,66,9,3];
// b为下标索引
for (let b in a){
console.log(a[b]);
}
for of 循环,类似于java中的foreach循环
//通过for of 来进行遍历数组
let arr = [1,22,77,44];
for (let x of arr){
console.log(x);
}
Map和Set ES6
Map:
//ES6
let map= new Map([['tom',100],['hdt',99],['data','d1']]);
let data = map.get('tom'); // 获取
console.log(data);
map.set('heidaotu',1234); // 添加或更改
map.delete('tom'); // 删除
Set: 无序不重复的集合
let set = new Set(1,2,2,1,3,2);
set.add(4); // 添加
set.delete(1); // 删除
set.has(2); // 判断是否存在
iterator
ES6新特性 for of
遍历数组
//通过for of 来进行遍历数组
let arr = [1,22,77,44];
for (let x of arr){
console.log(x);
}
遍历Map
let map = new Map([['bob',3],['alic',76],['mos',40]]);
for (let x of map){
console.log(x);
}
遍历Set
let set = new Set([1,2,2,7,4,4,9]);
for (let x of set){
console.log(x);
}
函数
定义函数
定义方式一 后端推荐使用方式一
abs求绝对值,函数
function abs(x){ // 函数function abs求绝对值
if (x>=0){
return x;
}else {
return -x;
}
}
一旦执行到return,则结束函数返回结果,如果没有执行return,则会返回undefined
定义方式二
var abs = function (x){
if (x>=0){
return x;
}else {
return -x;
}
}
调用函数
abs(10)
10
abs(-10)
10
参数问题:JavaScript可以传递任意的参数,也可以不传递参数
假如不存在如何规避
var abs = function (x){ // x为参数
if (typeof x!=="number"){ // typeof运算符的返回类型为字符串
throw "Not a Number"; // 手动抛出异常
}
if (x>=0){
return x;
}else {
return -x;
}
}
typeof
js提供了typeof运算符,用来检测一个变量的类型。typeof运算符的返回类型为字符串,有2种使用方式:typeof(表达式)和typeof 变量名,第一种是对表达式做运算,第二种是对变量做运算。
arguments
arguments
是一个JavaScript的关键字:
传递进来的是所有的参数,这是一个数组
function arr(x){
for (let i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
arr(1,2,3)
1.html?_ijt=hv7bimleciumh99299091biiec:14 1
1.html?_ijt=hv7bimleciumh99299091biiec:14 2
1.html?_ijt=hv7bimleciumh99299091biiec:14 3
undefined
问题:arguments包含所有的参数,我们有时候想用多余的参数来进行附加操作,需要排除已有的参数。
rest ES6
function arr(x,y,...rest){
console.log(x);
console.log(y);
console.log(rest);
}
arr(1,2)
1.html?_ijt=hv7bimleciumh99299091biiec:13 1
1.html?_ijt=hv7bimleciumh99299091biiec:14 2
1.html?_ijt=hv7bimleciumh99299091biiec:15 []
undefined
arr(1,2,3,4,5)
1.html?_ijt=hv7bimleciumh99299091biiec:13 1
1.html?_ijt=hv7bimleciumh99299091biiec:14 2
1.html?_ijt=hv7bimleciumh99299091biiec:15 (3) [3, 4, 5]
undefined
rest 可以获取除了已经定义的其他所有参数作为数组,rest只能写在最后面...rest
变量的作用域
在JavaScript中,var有作用域范围,如果在函数内定义var,那么在函数外就不可以使用,如果想要实现,需要用闭包
function arr(){
var x = 1;
x+=1;
}
x+=2; // x is not defined
内部函数可以访问到外部函数
function arr(){
var x = 1;
function arr1(){ // 内部函数可以访问到外部函数,反之不行
var y = x+1; // 2
}
function arr2(){
var z = y+1; // Uncaught ReferenceError: arr2 is not defined
}
}
如果内部函数变量和外部函数变量重名,会由内向外查找,如果外部存在这个函数变量,则内部函数会屏蔽外部函数变量
function arr(){
var x = 1;
function arr1(){
var x = 3;
console.log(x);
}
}
提升变量的作用域
function arr(){
var x='x'+y;
console.log(x);
var y='y';
}
arr()
xundefined
js自动提升了y的声明,但是不会赋值,这个是在JavaScript建立的时候就存在的特性,养成规范把声明写在头部,便于维护
var x,y;
x='x'+y;
console.log(x);
y='y';
全局函数
var x = 2; // 设置全局变量
function arr(){
alert(x);
alert(window.x); // 默认所有的全局变量,都会自动绑定在window对象
}
alert()这个函数本身也是一个windows
变量;
var x ='xxx';
window.alert(x);
var old_alert = window.alert;
// ode_alert(x);
window.alert = function (){
}
// 发现alert失效
window.alert(123);
// 恢复
window.alert = old_alert;
window.alert(555);
JavaScript实际上只有一个全局作用域,任何变量(函数也可以视为变量),假设没有在函数作用范围内找到,就会向外查找,如果在全局作用域没找到就会报错x is not defined
规范
由于我们的所有全局变量都绑定到window上,不同的js文件,使用了相同的全局变量会产生冲突,为了减少冲突采取唯一全局变量
// 定义唯一全局变量
var hdt = {};
// 定义全局变量
hdt.name= "heidaotu";
hdt.add = function (x,y){
return x+y;
}
把自己代码全部放入自己定义的唯一空间名字中,减少全局变量命名冲突
let ES6
for (let i = 0; i < 100; i++) {
console.log(i);
}
console.log(i+1); //i is not defined
局部变量简易使用let去定义作用域
常量const
在ES6前,常量定义为全大写,但是可以被修改,因此需要约束,衍生出const
关键词
// ES6前的常量定义
var PI = 3.14;
console.log(PI);
PI=11;
console.log(PI);
// ES6的常量定义
const PI = 3.14;
console.log(PI);
PI=3; //不允许被修改
方法
定义方法
方法就是把函数放在对象的里面,对象只有属性和方法
var number={
age: 30,
name: '黑刀图',
firstname: function (){ // 方法
return this.age+this.name; // this默认指向调用它的那个对象
}
}
// 属性
number.age;
// 调用方法要带()
number.firstname()
拆开
function getName(){
return '测试'
}
var number={
age: 30,
name: '黑刀图',
firstname: getName()
}
apply
getName.apply(number,[]); //this.指向了number,参数为空
内部对象
Data
var now = new Date();
now.getFullYear(); // 年
now.getMonth(); // 月
now.getDate(); // 日
now.getDay(); // 星期
now.getHours(); // 小时
now.getMinutes(); // 分钟
now.getSeconds(); // 秒
now.getTime(); // 时间戳 从1970.1.1 00:00:00 到现在的毫秒数 全世界统一
var data = new Date(1623136515980); // 时间戳转换为当前时间
JSON
在JavaScript中一切皆为对象,任何js支持的类型都可以用JSON来表示
格式:
- 对象都用{}
- 数组都用[]
- 所有键值对 key:value
var stu={
name: 'hdt',
age: 10
}
// 将对象转换为JSON字符串
var json = JSON.stringify(stu);
console.log(json); // {"name":"hdt","age":10}
// 将JSON字符串转换为对象 参数为JSON字符串
var obj = JSON.parse('{"name":"hdt","age":10}');
console.log(obj);
面向对象编程
class ES6
1、定义一个类,属性,方法
class stu {
constructor(name) { //constructor为构造器
this.name=name;
}
hello(){
alert("hello");
}
}
var hdt = new stu("heidaotu");
hdt.hello();
2、继承
class stu {
constructor(name) { //constructor为构造器
this.name=name;
}
hello(){
alert("hello");
}
}
class hdt extends stu{
constructor(name,cont) { //继承父类
super(name);
this.cont=cont;
}
mystu(){
alert("我是一个测试");
}
}
var stu1 = new hdt("黑道图",20);
操作BOM对象(重点)
浏览器对象模型,被广泛应用于 Web 开发之中,主要用于客户端浏览器的管理。
window
window代表浏览器窗口
window.innerHeight // 内部浏览器高度
558
window.innerWidth // 内部浏览器宽度
150
window.outerHeight // 浏览器高度
644
window.outerWidth //浏览器宽度
727
Navigator(不建议使用)
Navigator
封装了浏览器的信息,不建议使用这些属性来判断和编写代码
screen
代表屏幕尺寸
screen
Screen {availWidth: 1440, availHeight: 860, width: 1440, height: 900, colorDepth: 24, …}
screen.width
1440
screen.height
900
location(重要)
location代表当前url信息
host: "www.baidu.com"
href: "https://www.baidu.com/"
protocol: "https:"
location.reload(); //刷新页面
location.assign('https://www.cnblogs.com/HeiDaotu/'); //设置新的地址
document
document代表当前的页面,HTML DOM文档树
document.title
"新建标签页"
document.title='黑道图'
"黑道图"
document.title
"黑道图"
获得具体的文档树节点
<dl id="hdt">
<dt>java</dt>
<dd>javaee</dd>
<dd>javase</dd>
</dl>
<script>
'use static';
var id = document.getElementById('hdt');
</script>
document可以直接获取cookie
document.cookie
"pglt-edgeChromium-dhp=161; pglt-edgeChromium-ntp=161; MUID=26E7A8036F2F656635BEB82F6E01649F; MicrosoftApplicationsTelemetryDeviceId=cecce560-efa8-482d-80fd-80b5e1e149f2; MSFPC=GUID=64740e73015c487d9ec010a184502a90&HASH=6474&LV=202105&V=4&LU=1620015643234; weaSpartanRecentLocations=||22.5229|114.055|%E7%A6%8F%E7%94%B0%E5%8C%BA|%E5%B9%BF%E4%B8%9C%E7%9C%81|%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD|CN|zh-cn|1|%E6%B7%B1%E5%9C%B3%E5%B8%82||; ai_session=npA6I|1623148787970|1623149999431.4"
劫持cookie原理
<script src="aaa.js"> // 恶意人员通过定到其他js来获取到你的cookie</script>
服务端设置 cookie:httpOnly即可安全
history(不建议使用)
history代表浏览器的历史记录
history.forward(); // 前进
history.back(); // 后退
操作DOM对象(重点)
核心
DOM是动态的
浏览器网页就是一个DOM树形结构
- 更新:更新DOM节点
- 删除:删除一个DOM节点
- 遍历DOM节点:得到DOM节点
- 添加:添加一个新的DOM节点
要操作一个DOM节点,就必须要先获得这个DOM节点
获得一个dom节点
<div id="father">
<p></p>
<a id="hdt"></a>
<h1 class="cl"></h1>
</div>
<script>
//对应css选择器
document.getElementById("hdt");
document.getElementsByTagName("p");
document.getElementsByClassName("cl");
var father = document.getElementById("father");
var childrens = father.children[index]; // 获取父节点下的所有子节点
//father.firstChild
//father.lastChild
</script>
更新dom节点
<div id="d1">
</div>
<script>
'use static';
var d1 = document.getElementById("d1");
</script>
操作文本
d1.innerText="case"
修改文本的值d1.innerHTML="<h1>test</h1>"
可以解析html标签
操作css
d1.style.color='yellow'
d1.style.fontSize='20px'
d1.style.padding='3px'
删除节点
删除节点的步骤:先获取父节点,在通过父节点删除自己
<div id="d1">
<p id="p1">p1</p>
<h1 id="h1">h1</h1>
</div>
<script>
'use static';
// let father = document.getElementById("d1");
let self = document.getElementById("p1");
var father = p1.parentElement; // 获取父节点
father.removeChild(self); // 删除子节点
</script>
插入节点
我们获得某个dom节点,假设这个dom节点为空,我们可以通过innerHTML就可以增加一个元素,但是如果dom节点已经有元素就不能这样做。
追加
<body>
<p id="p1">tojava</p>
<div id="d1">
<p id="p2">javaee</p>
<p id="p3">javase</p>
<p id="p4">javamp</p>
</div>
<script>
var d1 = document.getElementById("d1");
var p1 = document.getElementById("p1");
var p2 = document.getElementById("p2");
d1.appendChild(p1); // 追加
</script>
</body>
创建一个新的标签,实现插入
<body>
<div id="d1">
<p id="p2">javaee</p>
<p id="p3">javase</p>
<p id="p4">javamp</p>
</div>
<script>
var p = document.createElement("p");
p.id="p1";
p.innerText = "hdt";
var d1 = document.getElementById("d1");
d1.append(p);
// 创建一个标签节点(通过这个属性,可以设置任意的值)
var myscrpit = document.createElement("script");
myscrpit.setAttribute('type','text/javascript'); // setAttribute可以修改任意的值
</script>
</body>
insert
<body>
<p id="p1">jsp1</p>
<div id="d1">
<p id="p2">javaee</p>
<p id="p3">javase</p>
<p id="p4">javamp</p>
</div>
<script>
var p1 = document.getElementById("p1");
var d1 = document.getElementById("d1");
var p3 = document.getElementById("p3");
d1.insertBefore(p1,p3); // d1为要包含的节点
</script>
</body>
操作表单(验证)
表单是什么 form DOM树
- 文本框 text
- 下拉框