前端基础:JavaScript
文章目录
前言
即使再小的帆也能远航
一、初始JS
0. 聊聊JavaScript这个东西
- 前端三要素
- HTML(结构)
- CSS(表现)
- JS(行为):是一种弱类型脚本语言,其源代码不需要经过编译,而是由浏览器解释运行,用于控制网页的行为
- CSS预处理器
- SASS(Ruby)、LESS(NodeJS)
- 行为层 JS
- Native原生JS开发
- ECMAScript标准
- …
- ES5(全浏览器都支持)
- ES6(常用,当前主流版本,webpack打包成为ES5支持)
- …
- ECMAScript标准
- TypeScript微软的标准
- Native原生JS开发
- JS框架
- JQuery:是一个库,优点是简化了DOM操作,缺点是DOM操作太频繁
- Angular:模块化开发
- React:虚拟DOM
- Vue:集大成,渐进式JS框架,综合了Angular和React的优点
- Axios:Ajax
- UI框架
- Ant-Design:React
- ElementUI、iview、ice:Vue
- Bootstrap
- AmazeUI
- JS构建工具
- Babel:JS编译工具,主要用于浏览器不支持的ES新特性,比如用于编译TypeScript
- WebPack:模块打包器,主要作用是打包、压缩、合并及按序加载
1. 什么是JS
JS是一门世界上最流行的脚本语言
2. 历史
Java、JavaScript
网景公司与JavaScript的起源故事
https://blog.csdn.net/kese7952/article/details/79357868
一个合格的后端人员,必须要精通JS
ECMAScript它可以理解为JS的一个标准
关键词,变量,流程控制,对象,数组,结构…
二、快速入门
1. 基本使用及HelloWorld
1. 引入JS
js放哪里都可以,最好放代码底部
(css有就近原则,最好放head里title后)
1、内部标签
2、外部引入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- script标签内,写JS代码 -->
<!-- <script>-->
<!-- alert('hello,world');-->
<!-- </script>-->
<!-- 外部引入 -->
<!-- 注意:script标签必须成对出现 -->
<script src="js/tutu.js"></script>
<!-- 不用显式定义type,也默认就是javascript -->
<script type="text/javascript"></script>
</head>
<body>
<!--js放哪里都可以-->
</body>
</html>
alert('hello,world');
2. 基本语法入门
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- JS严格区分大小写! -->
<script>
// 1. 定义变量:
// 变量类型 变量名 = 变量值;
// var num = 1;// var name = "tutu";//可以一层写多句代码
// alert(num);
// 可以下载JS强约束插件,下载后代码注释需第一个是空格才行,否则报错
// 2.条件控制
// if (2>1){
// if (2>2){// 可以随便多层嵌套
// alert("true");
// }
// }
var score = 150;
// if(score>=60 && score<75){
// alert("及格");
// }else if (score>=75 && score<85){
// alert("良好");
// }else if (score>=85 && score<=100){
// alert("优秀");
// }
// 上面的写法不好,每一次判断里的两个判断都有一次重复的判断
// 下面的对
if (score<60){
alert("不及格");
}else if (score<75){
alert("及格");
}else if (score<85){
alert("良好");
}else if (score<=100){
alert("优秀");
}else {
alert("false");
}
// 3.多行注释
/**
*
*/
/*
*/
// 4. 在浏览器的控制台打印变量! 相当于 System.out.println();
// console.log(score);
</script>
</head>
<body>
</body>
</html>
2. 浏览器控制台使用
浏览器控制台输出测试
浏览器源码断点调试
浏览器调试常用
3. 数据类型快速浏览
数值,文本,图形,音频,视频…
- 变量
// 变量的定义(var)与命名规范(与java一致)
// var 1a = 1;// 不能以数字开头
var $1 = 1;// 可以$开头
var _1 = 1;// 可以_开头
var 王者荣耀 = "最强王者";// 可以中文命名
- number
//js不区分小数和整数,Number
123//整数123
123.1//浮点数123.1
1.123e3//科学计数法,1123
-99//负数
NaN//not a number
Infinity//表示无限大
- 字符串
'abc'
"abc"
- 布尔值
true
false
- 逻辑运算
//与或非
&&//真真为真
||//一真为真
!//取反
- 比较运算符
=//赋值
==//等于(类型不一样,值一样,也会判断为true)
===//绝对等于(类型一样,值一样,结果为true)
这是一个JS的缺陷,坚持不要使用==比较
须知:
1、NaN === NaN,这个与所有的数值都不相等,包括自己
2、只能通过 isNaN()来判断这个数是否是NaN
- 浮点数问题
因为js里写的代码与java很像,所以也有浮点数问题
alert((1/3)===(1-2/3));
尽量避免使用浮点数进行运算,存在精度问题!
alert(Math.abs(1/3-(1-2/3))<0.000001);
-
null和undefined
null:空
undefined:未定义 -
数组:
Java的数组必须是一些列相同类型的对象,JS中不需要这样!
var arr = [1,2,3,4,5,'hello',null,true];
//保证代码的可读性,尽量使用上面这一种。基本类型用[],对象用{}
new Array(1,12,3,4,4,5,'hello');
取数组下标,如果越界了,就会报undefined
- 对象
对象是大括号,数组是中括号
var person = {
name:"tutu",
age:18,
tags:['js','java','web','...']
// tags 数组 最后一个不需要加逗号或分号
}
console.log(person);
alert(person.name);
每个属性之间使用逗号隔开,最后一个不需要添加
取对象的值
4. 严格检查模式strict
// 3.
// 使用严格检查模式
'use strict';
// 前提:IDEA需要设置支持ES6语法
// 预防js的随意性导致产生的一些问题
// 这句话写在js里的第一句,浏览器的控制台才会检查有无错误去报错
// 局部变量一般用let(或const)定义(意义一样)
// i = 1;
// 使用严格检查模式后,没有var会报错
//1.
// (定义在这个位置是)全局变量
var i = 1;
// var是自适应的,在方法内是局部,在方法外是全局
// 2.
// ES6,局部变量一般用let(或const)定义(意义一样)
// let m = 1;
// var相当于成员变量,let相当于局部变量
三、数据类型
1. 字符串类型详解
1、正常字符串我们是用单引号或者双引号包裹
2、注意转义字符 \ ,Unicode字符,AscII字符
'use strict';
// 转义字符,Unicode字符,AscII字符
console.log('a\nb');
console.log("a");
console.log('\u4e2d');//中
console.log("\x41");//A
3、多行字符串编写
// 多行字符编写 反引号 `` 在tab键上面,esc键下面
var msg =
`
你好
床前明月光
疑是地上霜
举头望明月
低头思故乡
`;
console.log(msg);
4、模板字符串
// 模板字符串(字符串拼接)
let name = "tutu";
let msg = `你好,${name}`;
console.log(msg);
5、字符串长度
// 字符串.length
var student = "student";
console.log(student)
console.log(student.length);
6、字符串的不可变性
// 字符串的不可变性
console.log(student[1]);
student[1] = 1;// 把'use strict'注释掉,发现字符未变化,不注释掉,会报错(控制台会在报错出停止继续编译)
console.log(student[1]);
console.log(student);
7、大小写转换
// 大小写转换
// 注意,这里是方法,不是属性了
// var studentUp = student.toUpperCase();
// console.log(studentUp);// STUDENT
// console.log(student.toLowerCase());
8、按值取位 / 按位取值
// 按值取位 / 按位取值
console.log(student.indexOf('d'));// 3
console.log(student.charAt(top));//
9、字符串截取
// 字符串截取
console.log(student.substring(3));// 3~end // dent
console.log(student.substring(1,3));// 1~3 //tu //左闭右开原则,即实际上是1~2
2. 数组类型详解
Array可以包含任意的数据类型
"use strict";//按 us + 回车 就出来了
// var arr = [1,2,3,4,5,6];
// console.log(arr);
// // 1. 数组长度
// console.log(arr.length);
// // 2. 通过数组下标取值或赋值
// // 取值
// console.log(arr[3]);
// // 赋值:数组内容可变
// arr[0] = 0;
// console.log(arr[0]);
// // 3. 数组长度可变。js可变,java不可变
// // 变长
// arr.length = 10;
// console.log(arr);// 新增空 empty
// console.log(arr[8]);// empty = undefined
// // 变短
// arr.length = 3;
// console.log(arr);// 元素丢失
// 4. 常用方法
// var a = [1,2,3,4,"1",'2'];
// // 1. 按值取位 按位取值
// console.log(a.indexOf(2));// 1 // 按值取位
// console.log(a[2]);// 3 // 按位取值
// // 2. 相同值不同类型的取位判断,且单引号或双引号识别到的是一样的
// console.log(a.indexOf(1));// 0
// console.log(a.indexOf("1"));// 4
// console.log(a.indexOf('1'));// 4
// console.log(a.indexOf(2));// 1
// console.log(a.indexOf("2"));// 5
// console.log(a.indexOf('2'));// 5
// // 3. slice 类似于字符串的substring
// // slice() 截取数组的一部分,返回一个新数组!
// console.log(a.slice(2));// [3, 4, '1', '2']
// console.log(a.slice(2,4));// [3, 4]
// // 4. 尾部操作:push压入、pop弹出 数值
// // 压入到尾部
// a.push("a","b");
// console.log(a);// [1, 2, 3, 4, '1', '2', 'a', 'b']
// // 弹出尾部的一个元素
// a.pop();
// console.log(a);// [1, 2, 3, 4, '1', '2', 'a']
// // 5. 头部操作:unshift压入、shift弹出 数值
// // 压入到头部
// a.unshift("a","b");
// console.log(a);// ['a', 'b', 1, 2, 3, 4, '1', '2']
// // 弹出头部的一个元素
// a.shift();
// console.log(a);// ['b', 1, 2, 3, 4, '1', '2']
// // 6. 不能中间加元素
// // 7. 排序(升序)
// a.sort();
// console.log(a);
// // [1, '1', 2, '2', 3, 4, 'b']
// // 8. 元素反转
// a.reverse();
// console.log(a);
// // 如果原来是升序的,那反转后就成了降序
// // 9. 拼接:concat
// var a = ["C","B","A"];
// a.concat([1,2,3]);
// console.log(a);// Array(3)
// var b = a.concat([1,2,3]);
// console.log(b);// ['C', 'B', 'A', 1, 2, 3]
// // 注意:结果不一样,concat并没有修改数组,只是会返回一个新的数组
// // 10. 连接符join
// // 打印拼接数组,使用特定的字符串连接
// a.join('-');
// console.log(a);// ['C', 'B', 'A']
// console.log(a.join('-'));// C-B-A
// //不影响原数组,打印出来一个字符串
// 11. 多维数组
// var a = [[1,2],[3,4],["a","b"]];
// console.log(a);// [Array(2), Array(2), Array(2)]
// console.log(a[1]);// [3, 4]
// console.log(a[1][1]);// 4
// // 测试不整齐数组
// var a = [[1,2],[3,4,5,6],["a","b"]];
// console.log(a);// [Array(2), Array(4), Array(2)]
// console.log(a.length);// 3
// // 12. 填充
// var a = [1,2,3,4,"1",'2'];
// a.fill(2,1,5);
// console.log(a);// [1, 2, 2, 2, 2, '2']
数组:如何存,如何取,方法都可以自己实现!
3. 对象类型详解
若干个键值对
var 对象名 = {
属性名:属性值,
属性名:属性值,
属性名:属性值
}
"use strict";
// 定义对象且赋值
var person = {
name:"tutu",
age:18,
score:100
}
//js中的所有的键都是字符串,值是任意对象!
console.log(person);
// 1. 取值
console.log(person.score);
console.log(person["age"]);// 用键(是个字符串,这里类似下标)取值
// 2. 使用一个不存在的对象属性,不会报错!会显示undefined
console.log(person.haha);// undefined
// 3. 动态的删减属性,通过delete删除对象的属性
delete person.name;
console.log(person);// {age: 18, score: 100}
// 4. 动态的添加,直接给新的属性添加值即可
person.haha = "haha";
console.log(person);// {age: 18, score: 100, haha: 'haha'}
// 5. 判断属性值是否在这个对象中!
console.log('age' in person);// true
console.log('toString' in person);// true // 继承
// 6. 判断一个属性是否是这个对象自身拥有的
console.log(person.hasOwnProperty('toString'));// false
console.log(person.hasOwnProperty('age'));// true
4. 流程控制(分支和循环详解)
"use strict";
// 1. 判断
// // if
// var score = 80;
// // 注意写好逻辑闭环,没必要条件写~~&&~~,因为他都是判断后一层一层往下走
// if (score<60){
// alert("不及格");
// }else if (score<75){
// alert("及格");
// }else if (score<85){
// alert("良好");
// }else if (score<=100){
// alert("优秀");
// }else {
// alert("false");
// }
// switch-case
// 2. 循环
// // while
// var age = 3;
// while (age<100){// 避免死循环
// age++;
// console.log(age);
// }
// // console.log()的快捷打法,直接输入 log + 回车
// do-while
// for
var age = [18, 3, 45, 17, 21, 6];
// 1. fori快捷输入
// for (let i = 0; i < age[i]; i++) {
// console.log(age[i]);
// }
// 2. forEach循环
// age.forEach(function (value){
// console.log(value);
// })
// 3.
// age.forEach(value => console.log(value));
// 4. forin ( for(Type str: el) ) ( for(var index in object) )
for (let ageKey in age) {
if (age.hasOwnProperty(ageKey)) {
console.log(ageKey);// 数组下标
console.log(age[ageKey]);// 数组值
}
}
// when
5. Map和Set集合
"use strict";
// ES6的新特性~
// // Map 存的是键值对
// // 学生的成绩,学生的名字
// var scores = new Map([ ['tom',100],['jack','90'],['haha',80] ]);// 存的是一个个键值对
// var score = scores.get('tom');// 通过key获得value
// // var scores = new Map([ ['1',100],['2','90'],['3',80] ]);// 键也可以是引号包裹的数字,所以可以用存学号的方式取成绩
// // var score = scores.get('2');
// console.log(score);
// scores.set('admin',60);// 新增或修改
// console.log(scores);// Map(4) {'tom' => 100, 'jack' => '90', 'haha' => 80, 'admin' => 60}
// scores.delete("jack");// 删除
// console.log(scores);// Map(2) {'tom' => 100, 'haha' => 80}
// // set 无序不重复 自动去重
var set = new Set([3,1,1,1,1]);
// console.log(set);// Set(2) {3, 1}
// set.add(1);// 添加
// console.log(set);// Set(2) {3, 1}
// set.add(2);
// console.log(set);// Set(3) {3, 1, 2}
// set.delete(1);// 删除
// console.log(set);// Set(2) {3, 2}
// console.log(set.has(3));// true // 包含判断
6. Iterable迭代器
"use strict";
// 遍历数组
var arr = [3,4,5];
// // forin
// for (let arrKey in arr) {
// console.log(arrKey);//下标
// }
// // forof
// for (let number of arr) {
// console.log(number);//值
// }
// 早期bug漏洞:forin
arr.name = 'tom';
for (let arrKey in arr) {
console.log(arrKey);
}
// 遍历 Map
var map = new Map([ ['tom',100],['jack','90'],['haha',80] ]);
for (let mapElement of map) {
console.log(mapElement);
}
// 遍历 Set
var set = new Set([5,6,7]);
for (let setElement of set) {
console.log(setElement);
}
四、函数及面向对象
0. 引入
c:方法:对象(属性,方法)
java:
public 返回值类型 方法名(){
return 返回值;
}
1. 函数定义及变量作用域
1. 函数的定义和参数获取
1. 定义函数
绝对值函数
function abs(x){
if (x>=0){
return x;
}else {
return -x;
}
}
"use strict";
// 定义方式一(偏后端爱用)
// function abs(x){
// if (x>=0){
// return x;
// }else {
// return -x;
// }
// }
//
// console.log(abs(10));// 10
// console.log(abs(-20));// 20
// function abs(x){
// return x>=0?x:-x;
// }
// console.log(abs(10));// 10
// console.log(abs(-20));// 20
//
// // undefined参与计算就会显示NaN
// console.log(abs());// NaN
//
// // 一旦执行到return,代表函数结束,返回结果!
// // 如果没有执行return,函数执行完也会返回结果,结果就是undefined
//
// console.log('bs');// bs
// console.log('~');// ~
// 定义方式二(偏前端爱用)
var abs = function (x) {
if (x >= 0) {
return x;
} else {
return -x;
}
}
console.log(abs(10));// 10
console.log(abs(-20));// 20
// 这是匿名函数用法,但是把结果值赋值给了abs,通过abs就可以调用函数!
// 方式一和方式二等价!
2. 调用函数
console.log(abs(10));// 10
console.log(abs(-20));// 20
3. 参数获取
// console.log(abs(-5,6,2,a,c));// a,c会报错
// console.log(abs(-5,6,2));// 5
// var abs = function (x) {
// var nums = arguments.length;
// if (nums>1){
// console.log(x);
// return nums;
// }
// if (x >= 0) {
// return x;
// } else {
// return -x;
// }
// }
//
// console.log(abs(-5,6,2));// 3 // 测试发现几个参数都会被传进函数内
// 参数问题:js可以传任意个参数,也可以不传递参数~
// 假设不存在参数,如何规避?
// 手动抛出异常来判断
// var abs = function (x) {
// if (typeof x!== 'number'){
// throw 'Not a Number';
// }
// if (x >= 0) {
// return x;
// } else {
// return -x;
// }
// }
// console.log(abs());// Uncaught Not a Number
// arguments 是一个js免费赠送的关键字
var abs = function (x) {
console.log("x=>" + x);
console.log("======");
for (let i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
console.log("======");
// 函数显式接受了一个参数,但其实所有参数都传进来了。arguments[1]这样可以隐式操作其他参数
if (arguments.length == 2) {
arguments[2];// 写操作第二个参数的操作
} else if (arguments.length == 3) {
arguments[3];// 写操作第三个参数的操作
} else {
// 其他
}
if (x >= 0) {
return x;
} else {
return -x;
}
}
console.log(abs(-5, 6, 2));
// arguments代表,传递进来的所有的参数,是一个数组
// 问题:arguments包含所有的参数,我们有时候想使用多余的参数来进行附加操作。需要排除已有参数~
// 类似 安全问题,只有开发者能做的操作
// rest ES6引入的新特性,获取已经定义的参数之外的所有参数 ~ java的可变参数 ... rest 剩余
function test(a,b,...rest){// rest参数只能写在最后面,必须用...标识// 发现rest用o替代也可以,即rest只是个约定俗成的名字,实际上是个数组名,叫啥都可以获取剩余的参数
console.log("a=>"+a);
console.log("b=>"+b);
console.log("rest=>"+rest);
console.log(a);
console.log(rest);
console.log(b);
}
test(2,6,7,3,9);
2. 变量的作用域、let、const详解
1. 变量的作用域
在js中,var定义变量实际是有作用域的。
假设在函数体中声明,则在函数体外不可以使用~ (闭包)
function test(){
var x = 1;
x = x + 1;
}
x = x + 2;// Uncaught ReferenceError: x is not defined
局部生效
如果两个函数使用了相同的变量名,只要在函数内部,就不冲突
function test(){
var x = 1;
x = x + 1;
}
function test2(){
var x = 1;
x = x + 1;
}
嵌套,内含同名变量,不报错
function test(){
var x = 1;
x = x + 1;
function test3(){
var x = 1;
x = x + 1;
}
}
内部函数可以访问外部函数的成员,反之则不行
function test(){
var x = 1;
x = x + 1;
function test3(){
x = x + 1;// 内部函数可以访问外部函数的成员,反之则不行
console.log(x);
var y = 2;
}
// var z = x + y;// Uncaught ReferenceError: y is not defined
test3();
}
// console.log(test().z);
test();
当内部函数变量和外部函数变量,重名,函数是从内向外查找变量的,内部覆盖外部,外部不受影响
function test(){
var x = 1;
x = x + 1;
function test3(){
// var x = 9;// 有无注释掉,有区别
console.log(x);
x = x + 1;// 注释掉后,访问的是外部函数的成员。
console.log(x);
}
test3();
}
test();
2. let、const详解
多个js文件引入后难免会有重名,所以推荐使用let
1、提升变量的作用域
// function test(){
// var x = "x" + y;
// console.log(x);
// var y = 'y';
// }
//
// test();// xundefined // 未报错
// 相当于下面的代码:
// 变量会先声明,后引用
function test(){
var x ;
var y ;
x = "x" + y;
console.log(x);
y = 'y';
}
test();// xundefined
结果:xundefined
说明:js执行引擎,自动提升了y的声明,但是不会提升变量y的赋值;
这个是在js建立之初就存在的特性。
养成规范:所有的变量定义一般会在都放在函数的头部,一次性声明,不要乱放,便于代码维护;
function test2(){
var x = 1,
y = x + 1,
z,i,a;// undefined
// 之后随意用
}
全局变量
var x = 1;
function f(){
console.log(x);
}
f();
console.log(x);
全局对象 window (window是浏览器查找的全局对象)
var x = 'xxx';
alert(x);
alert(window.x);// 默认所有的全局变量,都会自动绑定在window对象下;
alert()这个函数本身也是一个window变量
window.alert(x);// 和不写alert效果一样
// 1.
var x = 'xxx';
alert(x);
alert(window.x);// 默认所有的全局变量,都会自动绑定在window对象下;
1 和 2 效果一样
// 2.
var x = 'xxx';
window.alert(x);
var x = 'xxx';
var old_alert = window.alert;// 万物皆可对象
old_alert(x);// 调用window.alert成功
var old_alert = window.alert;
window.alert = function (){
};
window.alert(x);// 发现alert()失效了
// 恢复
window.alert = old_alert;
alert("成功");
js实际上只有一个全局作用域,任何变量(函数也可视为变量,万物皆可),假设没有任何函数作用范围内能找到,就会向外查找,如果在全局作用域都没有找到,会报错 ReferenceError
2、规范
由于我们所有的全局变量都会绑定到我们的window上,如果不同的js文件,使用了相同的全局变量,产生了冲突,那如何能够减少冲突呢?
// 唯一全局变量
var tutuApp = {};
// 定义全局变量
tutuApp.name= 'tutu';
tutuApp.add = function (a,b){
return a + b;
}
// 即,方法:定义一个对象把变量都装起来
把自己的代码全部放入自己定义的唯一空间名字中,降低全局命名冲突的问题
jQuery. 等价于 ${}
3、局部作用域
function test(){
for (var i = 0; i < 100; i++) {
console.log(i);
}
console.log(i+1);// i出了作用域还可以使用,问题?
}
test();
ES6 let 关键字,解决局部作用域冲突问题!
function test(){
for (let i = 0; i < 100; i++) {
console.log(i);
}
console.log(i+1);// 改成let后就会报错
}
test();
var只有函数作用域,let既有函数作用域,也有块作用域
建议大家都使用let去定义局部作用域的变量;
4、常量 const
在ES6之前,怎么定义常量:只要全部用大写字母命名的变量就是常量;建议不要修改这样的值;
var PI = 3.14;
console.log(PI);
PI = 222;
console.log(PI);// 值变了
在ES6引入了常量关键字 const
const PI = 3.14;// 常量:只读变量
console.log(PI);
PI = 222;
console.log(PI);// 报错了,Uncaught TypeError: Assignment to constant variable.
2. 方法的定义和调用、apply
1、定义方法
方法就是把函数放在对象delimma,对象只有两个东西:属性和方法
var tutu = {
name:'tutu',
birth:2000,
// 方法
age:function (){
// 今年 - 出生的年
var today = new Date();
// console.log(today);
var todayYear = today.getFullYear();
// console.log(todayYear);
var myAge = todayYear - this.birth;
// console.log(myAge);
return myAge;
}
}
// 属性:
console.log(tutu.name);
// 方法:一定要带括号
console.log(tutu.age());
console.log(tutu);
this.代表什么?拆开上面的代码看看
function getAge() {
// 今年 - 出生的年
var now = new Date().getFullYear();
return now - this.birth;
}
var tutu = {
name: 'tutu',
birth: 2000,
age: getAge
}
console.log(tutu.age());// 22
this是无法指向的,是默认指向调用它的那个对象;
2、apply
在js中可以控制this指向
function getAge() {
// 今年 - 出生的年
var now = new Date().getFullYear();
return now - this.birth;
}
var tutu = {
name: 'tutu',
birth: 2000,
age: getAge
}
var ming = {
name: 'ming',
birth: 2000,
age: getAge
}
getAge(tutu,[]);// this,指向了 tutu,参数为空
console.log(tutu.age());
getAge(ming,[]);// this,指向了 ming,参数为空
console.log(ming.age());
// 主动调用和被动调用的区别
主动调用和被动调用的区别!
五、内部对象
0. 引子
标准对象
typeof 123
'number'
typeof '123'
'string'
typeof true
'boolean'
typeof NaN
'number'
typeof []
'object'
typeof {}
'object'
typeof Math.abs
'function'
typeof undefined
'undefined'
1. Date日期对象
1、基本使用
var now = new Date();// Wed Sep 28 2022 07:25:56 GMT+0800 (中国标准时间)
now.getFullYear();// 年
now.getMonth();// 月 0~11 用时加一
now.getDate();// 日
now.getDay();// 星期几
now.getHours();// 时
now.getMinutes();// 分
now.getSeconds();// 秒
now.getTime();// 时间戳 全世界统一 1970.1.1 0:00:00 毫秒数
// 1664321266804
// 1664321266804/1000/60/60/24/365
// 52.7752811645104 (1970 - 2022)
console.log(new Date(1664321266804));// Wed Sep 28 2022 07:27:46 GMT+0800 (中国标准时间)
//时间戳转为时间:把时间戳放进来,就能得到日期
2、转换
var now = new Date(1664321266804);
console.log(now.toLocaleDateString());// 2022/9/28
console.log(now.toLocaleString());// 2022/9/28 07:33:43
console.log(now.toLocaleTimeString());// 07:33:43
// 注意,调用的是一个方法,不是一个属性!
console.log(now.toGMTString);// ƒ toUTCString() { [native code] } // 需要一个函数的意思
console.log(now.toGMTString());// Tue, 27 Sep 2022 23:27:46 GMT
2. JSON对象
早期,所有数据传输习惯使用XML
(科普,BSON)
1、JSON是什么
- JSON(JavaScript Object Notation, JS对象简谱)是一种轻量级的数据交换格式。
- 它基于 ECMAScript(European Computer Manufacturers Association, 欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。
- 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
- 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
在js一切皆为对象,任何js支持的类型都可以用JSON来表示;
格式:
1.对象都用{}
2.数组都用[]
3.所有的键值对 都是用 key:value
JSON字符串 和 JS对象的转化
var user = {
name:"tutu",
age:18,
sex:'女'
}
console.log(user);// {name: 'tutu', age: 18, sex: '女'}
// 对象转化为json字符串
var jsonUser = JSON.stringify(user);
console.log(jsonUser);// {"name":"tutu","age":18,"sex":"女"}
// json字符串转化为对象
var obj = JSON.parse(jsonUser);
console.log(obj);
var obj2 = JSON.parse('{"name":"tutu","age":18,"sex":"女"}');// parse里是String的 // 注意单引号和双引号
console.log(obj2);
JSON 和 JS 的区别
var obj = {a:'helloa',b:'hellob'};// 键值对
var json = '{"a":"helloa","b":"hellob"}';// 键也要是字符串,值也要是字符串,整个对象也要是字符串
3. Ajax
- 原生的js写法 xhr异步请求
- jQuery 封装好的方法 $(“#name”).ajax(“”)
- axios 是一个专门用来做请求的
六、面向对象编程
1. 面向对象原型继承
- 什么是面向对象
- JS、Java、C#、… 、面向对象;
- JS有些区别!
- 类:模板,原型对象
- 对象:具体的实例
- 在JS这个需要大家换一下思维方式!
- JS有些区别!
- JS、Java、C#、… 、面向对象;
- 原型:
// 原型对象
var User = {
name:"tutu",
age:18,
sex:'女',
run:function (){
console.log(this.name + " => run...");
}
};
var xiaoming = {
name: "xiaoming"
};
// 相当于复制后替换相同属性的值(克隆且覆盖)
xiaoming.__proto__ = User;
console.log(xiaoming.run());
console.log(xiaoming);
// 原型对象
var Bird = {
fly:function (){
console.log(this.name + " => fly...");
}
}
// 改变原型指向 从人变成了鸟
xiaoming.__proto__ = Bird;
console.log(xiaoming.fly());
2. 面向对象class继承(新特性)
class 关键字,是在ES6引入的
// 万物皆对象 这是个原型对象
function Student(name){
this.name = name;
// hello:function f(){
//
// }
}
// 给Student新增一个方法
Student.prototype.hello = function (){
alert("hello");
}
// ES6 之后 ========
// 定义一个学生的类
class Student{
// 构造器
constructor(name) {
this.name = name;
}
hello(){
alert("hello");
}
}
1、定义一个类,属性,方法
// 定义一个学生的类
class Student{
// 构造器
constructor(name) {
this.name = name;
}
hello(){
alert(this.name+" => hello");
}
}
var xiaoming = new Student("xiaoming");
var xiaohong = new Student("xiaohong");
xiaoming.hello();
console.log(xiaoming.name);
2、继承
// 定义一个学生的类
class Student{
// 构造器
constructor(name) {
this.name = name;
}
hello(){
alert(this.name+" => 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(this.name+" 是一名 "+this.grade+" 年级的小学生");
}
}
var xiaohong = new XiaoStudent("xiaohong",5);
xiaohong.hello();
xiaohong.myGrade();
本质:查看对象原型
3. 原型链继承(难点)
是个环形链
闭包(难点):类似装饰器
箭头函数(新特性)
七、操作BOM对象(重点)
0. 浏览器介绍
JS 和 浏览器的关系?
JS 诞生就是为了能够让他在浏览器中运行!
BOM:浏览器对象模型
浏览器内核
IE 6 - 11- Chrome(Windows)
- Safari(苹果)
- FifeFox(Linux)
- // Opera
第三方浏览器
- QQ浏览器
- 360浏览器
1. window(重要)
window 代表 浏览器窗口
(代表 全局对象)
window.alert(1)
undefined
window.innerHeight
178
window.innerWidth
767
window.outerHeight
816
window.outerWidth
1536
// 大家可以调整浏览器窗口试试...
2. navigator(不建议使用)
Navigator,封装了浏览器的信息
navigator.appName
'Netscape'
navigator.appVersion
'5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Edg/105.0.1343.50'
navigator.userAgent
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Edg/105.0.1343.50'
navigator.platform
'Win32'
大多数时候,我们不会使用navigator对象,因为会被人为修改!
不建议使用这些属性来判断和编写代码
3. screen
代表 屏幕尺寸
// 屏幕尺寸
screen.width
1536
screen.height
864
4. location(重要)
location 代表当前页面的URL信息
host:"www.baidu.com"
href:"https://www.baidu.com/?tn=15007414_8_dg"
protocol:"https:"
reload:ƒ reload()// 刷新网页 location.reload()
设置新的地址
如果在代码里写上location.assign(’ url ');
网站就会自动跳转到里面的url网页
location.assign('https://www.bilibili.com/');
// 设置新的地址
5. Document(内容:DOM)
document 代表当前的页面,HTML DOM 文档树
document.title
'百度一下,你就知道'
document.title='兔兔'
'兔兔'
获取具体的文档树节点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<dl id="app">
<dt>Java</dt>
<dd>JavaSE</dd>
<dd>JavaEE</dd>
</dl>
<script>
// 通过id获取节点信息
var dlmsg = document.getElementById('app');
console.log(dlmsg);
</script>
</body>
</html>
获取cookie
document.cookie
劫持 cookie 原理
淘宝 和 天猫:淘宝已登录状态,打开天猫,发现天猫读取了cookie,也是已登录状态
恶意人员:获取你的cookie上传到他的服务器
解决方法:服务器端可以设置 cookie:httpOnly
6. History
history 代表浏览器的操作记录
history.back();// 后退
history.forward();// 前进
八、操作DOM对象(重点)
1. 核心
- DOM:文档对象模型
- 整个浏览器网页就是一个DOM树形结构!
- 更新:更新DOM节点
- 遍历DOM节点:得到DOM节点
- 删除:删除一个DOM节点
- 添加:添加一个新的DOM节点
2. 获得DOM节点
- 要操作一个DOM节点,就必须要先获得这个DOM节点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="fatherDiv">
<h1>标题一</h1>
<p id="p1">p1</p>
<p class="p2">p2</p>
</div>
<script>
// 通过标签名获取节点 对应css选择器
var h1 = document.getElementsByTagName('h1');
var p1 = document.getElementById('p1');
var p2 = document.getElementsByClassName('p2');
var fatherDiv = document.getElementById('fatherDiv');
var childrens = fatherDiv.children; // 获取父节点下的所有子节点
console.log(childrens)// HTMLCollection(3) [h1, p#p1, p.p2, p1: p#p1]
// fatherDiv.firstChild;
// fatherDiv.lastChild;
// fatherDiv.children[index];
</script>
</body>
</html>
这是原生代码,之后我们尽量都用jQuery();
3. 更新DOM节点
- 通过JS操作文本
- Text 文本
- HTML 超文本
修改文本的值
div1.innerText='123';
可以解析HTML文本标签
div1.innerHTML='<strong><em>123</em></strong>';
2. 通过JS操作CSS
属性使用 字符串 包裹
驼峰命名问题(fontSize等)
div1.style.color = 'red';
div1.style.fontSize = '200px';
div1.padding = '2em';
4. 删除DOM节点
删除节点的步骤:先获取父节点,再通过父节点删除自己
<div id="father">
<h1>标题一</h1>
<p id="p1">p1</p>
<p class="p2">p2</p>
</div>
<script>
// 已知要删除的DOM节点的id名,来获取该标签元素
var self = document.getElementById('p1');
// 通过该标签获取父节点标签
var father = p1.parentElement;
// 通过父节点,删除id名为哪个的孩子节点
father.removeChild(p1);
</script>
注意:删除多个节点的时候,children是在时刻变化的,删除节点的时候一定要注意!
5. 创建和插入DOM节点
我们获得了某个DOM节点,假设这个DOM节点是空的,我们通过innerHTML / innerText 就可以增加一个元素了,但是这个DOM节点已经存在元素了,我们就不能这么干了!会产生覆盖~
追加
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<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>
</body>
</html>
<script>
var js = document.getElementById('js');
var list = document.getElementById('list');
list.appendChild(js);// 追加到后面,原来的位置就没了
</script>
效果:
通过JS创建一个新的节点
// 通过JS创建一个新的节点
var newP = document.createElement('p');// 创建一个p标签
newP.id = 'newP';
newP.innerText = '欢迎学习Java';
list.appendChild(newP);// 创建一个新的标签,实现插入
相当于
<p id="newP">
欢迎学习Java
</p>
创建一个标签节点
通过这个属性,可以设置任意的值
万能写法,能实现引入css文件或js文件
// 创建一个标签节点(通过这个属性,可以设置任意的值)
// (万能写法,能实现引入css文件或js文件)
var myScript = document.createElement('script');
myScript.setAttribute('type','text/javascript');
myScript.setAttribute('src','js/tutu.js');
console.log(myScript);// <script type="text/javascript" src="js/tutu.js">< /script>
// 记得追加
var list = document.getElementById('list');
list.append(myScript);
document.getElementsByTagName获得的是一个数组
var body = document.getElementsByTagName('body');
console.log(body);// HTMLCollection [body]
/*
0: body
length: 1
[[Prototype]]: HTMLCollection
*/
// 所以document.getElementsByTagName获得的是一个数组
var p = document.getElementsByTagName('p');
console.log(p);
/*
0: p#js
1: p#se
2: p#ee
3: p#me
ee: p#ee
js: p#js
me: p#me
se: p#se
length: 4
*/
// 果然是个数组
可以创建一个Style标签(多种方法)
// 可以创建一个Style标签
// // 1.
// var body = document.getElementsByTagName('body');
// // body[0].style.background = 'blue';
// // 2.
// body[0].setAttribute('style','background:blue');
// 3.
// 通过创建一个空style标签,然后设置标签内容,最后追加到head里
var myStyle = document.createElement('style');
myStyle.setAttribute('type','text/css');
myStyle.innerHTML = 'body{background:green;}';
// 将myStyle追加到head里
var head = document.getElementsByTagName('head');
head[0].appendChild(myStyle);
insert
var ee = document.getElementById('ee');
var js = document.getElementById('js');
var list = document.getElementById('list');
// 要包含的节点,insertBefore(newNode,targetNode);
// list.insertBefore(js,ee);// js插到了ee前
// 下面这样能实现ee插到js前
list.appendChild(js);
list.insertBefore(ee,js);
九. 操作表单(验证)
0. 回顾
之前:html基础验证(required的必填,disabled的禁用等)
表单是什么( form 、DOM树(树节点操作))
- 文本框 text
- 下拉框 select
- 单选框 redio
- 多选框 checkbox
- 隐藏域 hidden
- 密码框 password
- … …
表单的目的:获得要提交的信息
1. 获得和设置表单的值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post">
<p>
<span>名字:</span><input type="text" id="username">
</p>
<p>
<span>性别:</span>
<!-- 单选框的值,就是定义好的value name用于分组,没写就会导致变成多选 -->
<input type="radio" name="sex" value="men" id="boy"> 男
<input type="radio" name="sex" value="women" id="girl"> 女
<!-- 对于单选框活着多选框,他们的选项都有已经设置好的固定的值 -->
</p>
</form>
</body>
</html>
<script>
var input_username = document.getElementById('username');
// 可以取值,得到输入框的值
// input_username.value
// console.log(input_username.value);
// 修改输入框的值,设置默认值的一种方式
input_username.value = 'qiaqia';
var boy = document.getElementById('boy');
var gril = document.getElementById('girl');
console.log(boy.value);
console.log(girl.value);
// boy.checked // 可以用于检查单选框选项是否被选择,返回结果是true和false
// 查看返回的结果,是否是true,如果是true,则被选中~
boy.checked = true;// 也可以用这种方式来设置默认被选中
</script>
2. 表单提交验证及前端密码MD5加密
1、操作表单
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post">
<p>
<span>名字:</span><input type="text" id="username" required>
</p>
<p>
<span>性别:</span>
<!-- 单选框的值,就是定义好的value name用于分组,没写就会导致变成多选 -->
<input type="radio" name="sex" value="men" id="boy" disabled> 男
<input type="radio" name="sex" value="women" id="girl"> 女
<!-- 对于单选框活着多选框,他们的选项都有已经设置好的固定的值 -->
</p>
<p>
<input type="submit" value="点击提交">
</p>
</form>
</body>
</html>
<script>
// boy.checked // 可以用于检查单选框选项是否被选择,返回结果是true和false
// 查看返回的结果,是否是true,如果是true,则被选中~
// boy.checked = true;// 也可以用这种方式来设置默认被选中
</script>
设置必填项
设置禁用选项
2、表单提交验证
没有name的输入框,就不会被提交读取到值
<!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>
<!-- 文本框和密码框没有设置name属性,会获取不到值 -->
<!--<form action="https://www.baidu.com/" method="post">-->
<form action="https://www.baidu.com" method="post" onsubmit="return login()">
<p>
<span>名字:</span><input type="text" id="username" name="username" required>
</p>
<p>
<span>密码:</span><input type="password" id="password" name="password" required>
</p>
<p>
<!-- <input type="submit" value="点击提交">-->
<!-- <input type="button" name="submit" value="点击提交">-->
<!-- <button type="submit" οnclick="login()">点击提交</button>-->
<button type="submit">点击提交</button>
</p>
</form>
</body>
</html>
<script>
function login(){
var username = document.getElementById('username');
var password = document.getElementById('password');
console.log(username.value);
console.log(password.value);
// alert(username);// [object HTMLInputElement]
if (username.value === password.value){
return true;
}else {
return false;
}
}
</script>
3、前端密码MD5加密
测试md5加密是否成功
<!-- 导入MD5工具类 -->
<script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js"></script>
<script>
function login(){
var username = document.getElementById('username');
var password = document.getElementById('password');
console.log(username.value);
console.log(password.value);
// 安全加密 防止审查发现网络请求中的密码
// password.value = "*****";
// MD5 算法
password.value = md5(password.value);
console.log(password.value);
}
</script>
优化
<!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="https://www.baidu.com" method="post" onsubmit="return login()">
<p>
<span>名字:</span><input type="text" id="username" name="username" required>
</p>
<p>
<span>密码:</span><input type="password" id="password" name="password" required>
</p>
<p>
<input type="hidden" id="md5-password" name="md5-password" required>
</p>
<p>
<button type="submit">点击提交</button>
</p>
</form>
</body>
</html>
<script>
function login(){
var username = document.getElementById('username');
var password = document.getElementById('password');
var md5pwd = document.getElementById('md5-password');
md5pwd.value = md5(password.value);
// 可以校验判断表单内容,true就是通过提交,false阻止提交
return true;
}
</script>
操作文件
十、jQurey
0. 推荐使用
jQuery API 中文文档 | jQuery API 中文在线手册
jQuery API 3.5.1 速查表 --作者:Shifone
https://jquery.cuishifeng.cn/
1. 初始jQurey及公式
JavaScript
jQuery库,里面存在大量的JS函数(封装)
1、获取jQurey(下载)
https://jquery.com/
Download the compressed, production jQuery 3.6.1
已编译好的,生产,带min
Download the uncompressed, development jQuery 3.6.1
未编译的,开发,不带min
CDN jQuery :在线的链接
jQuery cdn加速
https://www.jq22.com/cdn/
右键,链接另存为即可下载
BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务
https://www.bootcdn.cn/
https://www.bootcdn.cn/jquery/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- cdn引入 -->
<!-- <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>-->
<!-- 本地导入-->
<script src="lib/jquery-3.6.1.js"></script>
<!--
公式:$(selector).action() ~~ jQuery.选择器.行为
-->
</head>
<body>
<a href="" id="test-jquery">点我</a>
</body>
</html>
<script>
// 之前
// var id = document.getElementById('test-jquery');
// id.click(function (){alert('before')});
// 现在
// 选择器就是css的选择器
$('#test-jquery').click(function (){alert('hello,jquery')});
</script>
2. jQurey选择器
// 原生js,选择器少,麻烦不好记
// 标签
// document.getElementsByTagName()
// id
// document.getElementById()
// 类
// document.getElementsByClassName()
// jquery css中的选择器他全部都能用!
// 标签选择器
// $('p').click()
// id选择器
// $('#id1').click()
// 类选择器
// $('.class1').click()
文档工具站
https://jquery.cuishifeng.cn/
3. jQurey事件
鼠标事件,键盘事件,其他事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#divMove{
width: 500px;
height: 500px;
border: 1px solid red;
}
</style>
</head>
<body>
<!--要求:获取鼠标当前的一个坐标-->
mouse : <span id="mouseMove"></span>
<div id="divMove">
在这里移动鼠标试试
</div>
</body>
</html>
<!--别忘记导入jQuery-->
<script src="lib/jquery-3.6.1.js"></script>
<script>
// 当网页元素加载完毕之后,响应事件
// $(document).ready(function (){})
// 简写后
$(function (){
$('#divMove').mousemove(function (e){
$('#mouseMove').text('x:'+e.pageX + ',y:'+e.pageY);
})
});
</script>
4. jQurey操作DOM元素
节点文本操作
// 之前
// document.getElementById('')
// 现在
// 节点文本操作
// 获得值:text参数为空,是取值
// $('#test-ul li[name=python]').text();// 'Python'
// 设置值:有参数就是赋值
// $('#test-ul li[name=python]').text('jQuery');// jQuery.fn.init [li, prevObject: jQuery.fn.init(1)]
$('#test-ul').html();// 一样
css的操作
// css的操作 里面放键值对
// 单属性
$('#test-ul li[name=python]').css("color","red");
// 多属性
$('#test-ul li[name=python]').css({"color":"red","font-size":"10px"});
元素的显示和隐藏
本质:display:none
$('#test-ul li[name=python]').hide();
$('#test-ul li[name=python]').show();
娱乐测试
$(window).width()
$(window).height()
$(document).width()
// toggle 转换状态(当设置了隐藏,输入这个代码会变成显示)
$('#test-ul li[name=python]').toggle();
未来学习Ajax
$('#form').ajax()
$.ajax({ url: "test.html", context: document.body, success: function(){
$(this).addClass("done");
}});
前端小结及开发技巧分享
ant design
vue press
docsify
1、如何巩固JS(看jQuery源码!)
2、巩固HTML、CSS(扒网站,全部down下来,然后对应修改看效果~)
闭包
公式:$(选择器).事件(事件函数)
Layui
Layer弹窗组件
https://layuion.com/layer/
element ui
https://element.eleme.io/#/zh-CN/component/installation
bootstrap
https://www.bootcss.com/
ant design
https://ant.design/components/overview-cn/
docsify
https://docsify.js.org/#/