在被AI替代前的倔强:学习JavaScript
0. 前言
截止至本文攥写时,Chat GPT 又发布了重磅插件:Code Interpreter,进一步加剧了程序猿被AI取代的忧虑,毕竟,个人学习的速度,甚至一线开发团队整体学习的速度远远比不上 AI 的迭代速度。那怎么办呢,一来我们要拥抱变化,打不过就加入;二来可以在业余,通过补充技术的广度入手,通过技术的学习,脑子里留个印象,方便日后使用工具进行代码生成后,能看懂,会调试。
作为后端程序猿,后端语言的重要性不言而喻,短期内暂时不会被AI取代,但在前端,Java Script 作为应用极广的语言,我们有必要进行系统的学习。
在学习 Java Script 之前,我们首先要掌握 Html 与 CSS 的基础,以便更好地练习与理解。
学习目标
快速学习/复习 Java Script 基础。
参考教程
CSDN-参考博文:https://blog.csdn.net/weixin_43779187/article/details/125831991
注意,本文篇幅较长,可以先收藏,再慢慢看。
1. Java Script
完整的 Java Script 由基本语法结合BOM 、DOM 的概念与操作组成。本小节先介绍 Java Script 相关语法。
1.1 Java Script 特性
- 属于脚本语言,不需要编译,又浏览器解析执行
- 支持面向对象
- 弱类型语言,不太重视类型的匹配
- 安全性强,交互性强
- 跨平台,有强大的生态系统
1.2 Java Script 引入方式
与 CSS 类似,Java Script 引入方式分为内联、内部、外部。
1.2.1 内联
内联实际用得较少,通过属性添加,我们了一下即可:
<!-- 内联样式,直接在属性中添加 -->
<input type="button" value="按钮" onclick="alert('Hello JavaScript!')">
1.2.2 内部
内部样式通过<script>
标签引入,是我们常用的引入方式:
<script>
// 浏览器控制台输出
console.log("Hello JavaScript!")
</script>
注意,<script>
标签的位置建议:当我们要定义全局变量时,<script>
标签建议写于<head>
标签内;当我们要嵌入少量JS代码时,为了使代码在页面加载过程中执行,<script>
标签建议写在<body>
标签内:
<!DOCTYPE html>
<html>
<head>
<script src="script.js"></script> <!-- 引入外部的JavaScript文件 -->
<script>
// 在这里定义全局变量或者其他执行的代码
</script>
</head>
<body>
<!-- 页面内容 -->
<script>
// 在这里编写JavaScript代码
</script>
</body>
</html>
1.2.3 外部
外部引入方式有利于代码结构化、文件级别代码复用。
但需注意:如果是外部引入的Java Script,<script>
标签内就不能写其他内容了。
//外部.js文件的内容
console.log("Hello JavaScript");
<!--以下是引入方式-->
<script src="fileName.js"></script>
1.3 Java Script 基本语法
如果您有其他编程语言基础,那么 JS 的语法就可以快速掌握,大部分通用。
1.3.1 变量
JS 变量的声明 通常有 隐式声明(不由任何关键字声明)、var 关键字声明、 let 关键字声明、 const 关键字声明 这几种方式。
全局变量
当我们声明变量时不添加任何关键字时,默认为全局变量:
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Java s cript leanring</title>
<script>
// 定义全局变量
x = 1;
</script>
</head>
var
var 声明的变量比较灵活。当 var 声明的变量在方法内时,该变量的作用域仅为该方法内;当该变量的声明在方法外时,该变量可视为全局变量。 由于 var 过于灵活,不利于作细致的区分,我们现在也用得较少。
<script>
var z = 0;
function myFunction(){
var y = 2;
console.log(x);
console.log(x+y);
console.log(z);
}
function logz(){
console.log(z+1);
}
myFunction();
logz();
</script>
<script>
function writeZ(){
document.write(z);
}
writeZ();
</script>
let
用 let 声明的变量作用域在块内,超出该代码块则不可访问。用 let 声明的变量是局部变量。 但值得注意的是,如果我们非要将let声明在代码块外,依然可以视为全局变量,但我们一般不这么用。
<script>
let a = "hello";
function fun(){
let b = "world";
console.log(b);
}
console.log(a);
fun();
</script>
const
const 关键字声明的是常量,必须在声明时就赋值。常量不可修改。它的作用域特性与let一样,拥有块级作用域。
<script>
function example(){
const c = "name";
console.log(c);
// 报错,常量不可修改
// c = "1";
}
example();
</script>
1.3.2 数据类型
JS 只有对象类型,没有基本类型。
对象类型
- String 字符串,可以由双引号或单引号修饰
- Number 数字,包括整型和浮点数
- Boolean 布尔类型
特殊类型
- undefined 未定义,声明了但未赋值
- null, 空
类型相关常用方法
- typeof
- toString :转换为 字符串
- parse :转换为相应数字类型
综合举例:
<script>
var a = "hello script";
let b = 5;
let c = 1.7;
let d = true;
let aString = "这是一个字符串";
//将以上数据的类型看作文档,写在页面中
document.write(typeof a);
document.write(typeof b);
document.write(typeof c);
document.write(typeof d);
document.write(isNaN(aString));
let aNum = "16";
document.write(typeof aNum);
let changeNum = parseInt(aNum);
document.write(typeof changeNum);
let bNum = "17.3";
let changeNumb = parseFloat(bNum);
console.log(typeof changeNumb);
</script>
1.3.3 运算符、控制流程与函数
(1) JavaScript运算符
运算符的 加、减、乘、除、三目、赋值等与JAVA等高级语言相同。
逻辑运算符:只支持短路与、短路或、非,即:&&、|| 、!
比较:
== 双等号:先统一类型,再比较值;
=== 三连等:先比较类型,类型相同后再比较值;
以上与高级语言不同的部分举个例子:
<script>
let a = true;
let b = false;
let c = 15;
let d = "15";
//只能使用短路与、或
document.write(a&&b);
//比较:===
console.log(c===d);
//比较:==
console.log(c==d);
</script>
(2) JavaScript控制流程
JS的控制流程和JAVA、C等语言基本一致,都有if-else、switch分支、for、while、do-while循环等控制流程。
因为语法基本一致,单词关键词也几乎没有区别,此处不赘述。具体的例子在下面的知识点的例子中体现。
(3) JavaScript方法(函数)
函数是本段落的重点,因为函数的定义方式与调用方式与高级语言略有不同。
函数的声明:
1)使用大写开头的Function:
最不常用,这种方式了解一下即可:
let f = new Function ("name","age","console.log(name+age)");
f("Sharry","20");
2)声明方式二:
这种也不算太常用。直接用一个变量接收方法(函数)。
let f = function (hello,action){
console.log(hello+action);
}
f("您好","请上车");
3)声明方式三:
这是常用的声明方式;
function f4(x,y){
return x*y;
}
let result = f4(3,4);
console.log(result)
小总结一下:以上方法的声明,常用的是:
function 方法名(参数){
方法体;
//根据业务需要是否要返回值
return xxx;
}
调用方法:类似于高级语言的方法调用方式。
结合控制流程,举个综合小例子:
<input type="text" id = "i1">
<input type="button" value="平方" onclick="f()">
<div>
结果:<span></span>
</div>
<script>
function f(){
/*获取元素*/
let i = document.querySelector("#i1");
let result = document.querySelector("div>span");
if(isNaN==(i.value)){
s.innerText = "输入错误!";
return;
}
result.innerText = i.value * i.value;
}
</script>
1.3.4 异常处理
JavaScript的异常处理通常采用try-catch-finally结构。
直接举个例子体现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS异常处理</title>
</head>
<body>
<script>
function f1(){
document.write("这是一个普通方法f1<br>");
}
/*此时如果执行一个没有被定义的语句,例如输出一个未被定义的变量,就会出错
* 出错不处理的话,之后的代码浏览器都不会执行,因此需要使用try-catch-finally解决
* */
try{
f1();
//未被获取或者定义的变量,此处querySelector获取的id并不存在
let c = document.querySelector("#undefinded");
document.write(c.value);
}catch (e){
console.log(e.message);
document.write("执行了catch里的语句<br>");
}finally{
document.write("和JAVA语言一样,finally里的代码无论前面异常是否catch到,必执行<br>");
}
document.write("最后执行的代码");
</script>
</body>
</html>
1.3.5 对象
前面提到过,JS支持面向对象,在JS中,没有基本数据类型,所有数据类型都是对象类型。同时JS是弱类型语言,在一些情况下不需要进行特意的数据类型转换,举个例子:
<!--JS弱类型例子-->
<script>
//先把a定义成字符串
let a = "string";
//再将a赋值成数字,直接转换成number类型
a = 123;
document.write(typeof a);
</script>
<!--JS对象例子-->
<script>
//类似于JAVA的new对象
let b = new Number(123);
document.write("<br>"+b.toString());
document.write("<br>");
document.write(typeof b);
</script>
接下来介绍JS常见对象及常用方法。
(1) 数字Number
Number对象是数字对象。
创建Number:
let b = new Number(123);
常见方法
- isNaN():是否未非数字,是的话未true,否的话未false
- toFixed():返回小数表达
- toExponential():返回科学计数法表达
- valueof():返回数字类型
一起举个例子:
<!--数字常用方法例子-->
<script>
let c = new Number(123);
//是否未数字
document.write("<br>"+isNaN(c));
document.write("<br>");
//小数表达
document.write(c.toFixed());
document.write("<br>");
//科学计数
document.write(c.toExponential());
document.write("<br>");
//数字类型
let d = c.valueOf();
document.write(typeof d);
</script>
(2) 字符串String
JS的字符串与JAVA的字符串很像,这里介绍一些常见方法:
常见方法
- concat:字符串拼接
- indexOf:字符出现的位置
- replace:替换字符
- localeCompare:比较字符串是否相同
- split:将字符串转换成数组
这些方法与JAVA中的String相关方法类似,这里直接举一个例子体现一下:
<script>
let s = new String("AString");
//返回指定位置字符
document.write(s.charAt(0));
document.write("<br>");
//拼接
let target = "Yp!";
s = s.concat(target);
document.write(s);
document.write("<br>");
//比较是否相同
let isTheSame = "AStringYp!";
//0:相等
document.write(s.localeCompare(isTheSame));
document.write("<br>");
//1:字母顺序靠前
document.write(target.localeCompare(isTheSame));
document.write("<br>");
//-1:字母顺序靠后
document.write(isTheSame.localeCompare(target));
document.write("<br>");
//替换掉字符,此方法可以一个也可以是多个
let replace = s.replace("t","T");
document.write(replace);
document.write("<br>");
//分割成数组
let a = "It is a String";
let b = a.split(" ");
document.write(b);
</script>
(3) 数组Array
JS的数组的长度可以随时发生变化,与JAVA略有不同。
创建数组:
<script>
//创建新数组,没有赋值的情况下元素都是undefined
let arr1 = new Array(3);
//返回长度
console.log(arr1.length);
//循环遍历、赋值
for (let i = 0; i < arr1.length; i++) {
arr1[i] = i;
console.log(arr1[i]);
}
//直接赋予长度与初值的创建方法
let arr2 = new Array(5,7,84,2);
for (let j = 0 ; j < arr2.length ; j++){
document.write(arr2[j]);
}
</script>
数组常用方法:
- reverse():反转数组
- sort():排序
- concat():连接数组
- splice():删除和插入元素
例子:
<script>
let arrOne = new Array(1,2,3);
let arrTwo = new Array(55,6,89,32,3);
//连接两个数组
let arrResult = arrOne.concat(arrTwo);
document.write(arrResult);
document.write("<br>");
//排序
document.write(arrResult.sort());
document.write("<br>");
//反转
document.write(arrOne.reverse());
document.write("<br>");
//删除、插入
let arrThree = new Array(9,8,7,6,5,4,3,2,1,0);
//删除 起始位置,删除个数
arrThree.splice(0,2);
document.write(arrThree);
document.write("<br>");
//插入 起始位置,删除个数,插入元素
arrThree.splice(4,3,23,44,55);
document.write(arrThree);
document.write("<br>");
//只插入试试
arrOne.splice(0,0,-2,-1);
document.write(arrOne);
</script>
(4) 日期Date
JS也带有表示日期的对象。
常用方法:get、set方法,这里的方法比较简单,直接上例子体现一下:
<script>
//创建日期对象
let d = new Date();
//用自定义的输出方法输出当前日期
print(d);
//get方法,分别对用年月日,注意,因为这个方法默认一月的返回值是0,所以正确显示要加1
print(d.getFullYear());
print(d.getMonth()+1);
print(d.getDate());
//同理有时分秒
print(d.getHours());
print(d.getMinutes());
print(d.getSeconds());
//set方法,设置时间,能get到的时间元素都能通过set设置
d.setFullYear(2021);
d.setHours(23);
print(d);
function print(element){
document.write(element);
document.write("<br>");
}
</script>
(5) 自定义对象
既然JS支持面向对象,那么肯定支持自定义对象。
JS自定义对象:通过new Object的方式创建对象,再给对象设置属性、方法,举个例子
<!--new Object 创建自定义对象-->
<script>
//创建怪兽对象
let monster = new Object();
//定义属性同时赋值
monster.name = "青眼白龙";
//定义方法同时写方法体
monster.skill = function (){
console.log("青眼白龙没有效果");
}
monster.skill();
</script>
第二种创建方式通过对像名大括号{}的形式创建,举个例子:
//键值对的方式定义属性和方法
let fruit = {
name:"orange" ,
color:"orange" ,
eat : function (){
console.log("吃起来是酸甜的");
}
}
fruit.eat();
第三种创建方式,直接通过function创建
<!--直接通过function 创建自定义对象-->
<script>
//function
function blackMagic(name,attack){
this.attack = attack;
this.name = name;
this.skill = function (){
console.log("黑魔术师没有效果");
}
}
let b = new blackMagic("黑魔术师",2500);
b.skill();
</script>
实际开发中,我们将第二种创建方式的对象封装成数组的情况比较多,举个例子:
//对象数组
let arr = [{width:500, height:30, read:"足球场规格"},
{width:500, height:30, read:"篮球场规格"},
{width:500, height:30, read:"家里宽高"}];
2. BOM 和 DOM
2.1 BOM
BOM : Browser Object Model ,浏览器对象模型,包括和浏览器相关的内容。
因此本章节部分例子是在浏览器自带工具的控制台输出的代码
2.1.1 窗口Window
一旦创建页面,默认自动创建window对象。这个对象里面的属性和方法是全局的属性和方法,访问时可以省略掉window.
//弹出确认框
confirm("xxx")
//弹出提示输入框
prompt("xxx")
//弹出提示框
window.alert("xxx")
BOM还能进行定时器设置,也是window中的常见方法,举个例子:
<script>
//开启定时器,每隔一秒调用一次
//方法作为参数传递时,不写括号()
let count = 0;
setInterval(f,1000);
function f(){
count ++ ;
let h = document.querySelector("h1");
h.innerText = count;
}
//匿名方法开启定时器
let num = 0;
let timer = setInterval(function (){
num++;
let h = document.querySelector("h2");
h.innerText = num;
if(num == 100){
clearInterval(timer);
}
},100);
//开始只执行一次的定时器
setTimeout(function (){
alert("时间到!")
}, 3000);
</script>
2.1.2 浏览器Navigator
BOM包含浏览器对象,提供浏览器相关信息,通过navigator.访问这些信息。
//以下代码可以直接在浏览器自带的工具测试输出,输出结果分别对应方法名所显示的信息
navigator.appName
//'Netscape'
navigator.appCodeName
//'Mozilla'
navigator.appVersion
//'5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0...
navigator.cookieEnabled
//true
2.1.3 客户端屏幕Screen
与Navigator类似,Screen包含的是客户端屏幕的相关信息,此处直接举例子:
screen.width
//1920
screen.height
//1080
2.1.4 访问历史History
history:当前浏览器的历史
history.length 历史长度
history.back()后退
history.forward() 前进
history.go(n) 1 下个页面 -1 上一页面 0刷新 ,其他参数:前/后若干个网站的记录
<script>
function goBack(){
console.log(history.length);
history.back();
}
</script>
<button onclick="goBack()">返回</button>
2.1.5 浏览器地址Location
location表示浏览器中的地址栏里的地址,我们通过location可以跳转到指定网页
当然,location也包含了很多其他属性,例如协议、主机名、端口号等。感兴趣的同学可自行查阅测试。
//跳转到指定网址,url填写地址名
location.herf = "url"
//刷新网页
location.reload()
2.2 DOM
Document Object Model ,文档对象模型,包括和页面标签相关的内容。
DOM是将html里面的元素看作一个个节点,将数据当作对象进行相关操作。
最大的节点是整个HTML文档,各种元素是节点,如div、body等标签,元素的属性、内容也算节点。
但在实际开发中,由于目前主流框架一定程度上已经舍弃了DOM,所以实际用得极少,本章节作为了解供读者参考。
举个例子:
<body>
<div id = "d1">Hello DOM</div>
<script>
/*在JS中测试一下节点*/
//接收元素
let dPoint = document.querySelector("#d1");
function testPoint(e){
console.log(e);
}
//输出文档节点
testPoint(document);
//输出元素节点
testPoint(dPoint);
//输出属性节点
testPoint(dPoint.attributes);
//输出内容节点
testPoint(dPoint.childNodes);
</script>
</body>
2.2.1 DOM创建节点
创建节点:document.createElement(节点名);
将节点插入页面:document.body.append(节点名);
举两个例子:
<script>
//创建标签
let d = document.createElement("div");
//给div设置显示文本
d.innerText = "这是div";
//把div添加到body里面
document.body.appendChild(d);
//添加多个标签
let h1 = document.createElement("h1");
let h2 = document.createElement("h2");
h1.innerText = "这是h1";
h2.innerText = "这是h2";
document.body.append(h1,h2);
//创建图片并添加
let i = document.createElement("img");
//给元素设置属性
i.src = "../orange.png";
//添加到页面中
document.body.append(i);
</script>
图片添加小练习:
<!--读者在参考该小练习的时候要注意图片名、路径按照自己的图片实际路径来测试-->
<body>
<input type="text" id = "d1">
<input type="button" value="添加orange" onclick="add(1)">
<input type="button" value="添加apple" onclick="add(2)">
<script>
function add(type){
//获取输入框元素并判断是否为非数字
let num = document.querySelector("#d1");
if(isNaN(num.value)){
let wrongResult = document.createElement("div");
wrongResult.innerText = "输入错误,请输入正确的数字";
document.body.appendChild(wrongResult);
location.reload();
return;
}
switch (type){
case 1:
for (let i = 0; i < num.value; i++) {
let orange = document.createElement("img");
orange.src = "../orange.png";
document.body.appendChild(orange);
}
break;
case 2:
for (let i = 0; i < num.value; i++) {
let apple = document.createElement("img");
apple.src = "../apple.png";
document.body.appendChild(apple);
}
break;
default:
return;
}
}
</script>
2.2.2 DOM获取节点
获取节点可以通过上面例子常用的document.querySelector(“选择器”)
也可以通过document.getElement方法获取,具体方法:
getElementById():通过id获取元素节点,返回一个元素;
getElementsByTagName():通过标签名获取元素节点,返回一个数组;
getElementsByClassName():通过class属性获取节点,返回一个数组;
getElementsByName():通过name属性获取节点,返回一个数组;
上栗子:
<body>
<h1 id = "d1"></h1>
<div class = "c1">div1</div>
<div class = "c1">div2</div>
<div class = "c1">div3</div>
<span>span1</span>
<span>span2</span>
<span>span3</span>
输入框1<input type="text" name="in1">
输入框2<input type="text" name="in1">
<script>
let l1 = document.getElementById("c1");
console.log(typeof l1);
let l2 = document.getElementsByClassName("c1");
logElements(l2);
let l3 = document.getElementsByTagName("span");
logElements(l3);
let l4 = document.getElementsByName("in1");
logElements(l4);
function logElements(e) {
for (let i = 0; i < e.length; i++) {
console.log(e[i]);
}
}
</script>
2.2.3 删除节点
上面提到过创建节点createElement和插入节点append,这里再介绍一下删除节点removeChild
<div id="d1"></div>
<button onclick="removeDiv()">删除节点</button>
<script>
function removeDiv(){
let removeObject = document.getElementById("d1");
document.body.removeChild(removeObject);
}
</script>
3. 总结与补充
本文介绍了JAVAScript的基本语法、BOM和DOM的相关概念。
但在实际开发中,由于DOM操作存在效率问题,因此目前市面上常用基于MVVM设计模式的VUE前端框架、大厂目前流行VUE同时期产物React。这些框架不需要我们直接操作DOM,可以认为,这些框架是为我们免除了DOM。