JavaScript
JavaScript 是属于 HTML 和 Web 的编程语言。
web 前端的三种语言:
- HTML 定义网页的内容
- CSS 规定网页的布局
- JavaScript 对网页行为进行编程
- ECMAScript:简称【ES】,它是欧洲计算机协会,大概每年六月中旬定制的语法规范。
- DOM(document object model):文档对象模型
- BOM(browser object model):浏览器内置的window对象,可以获取浏览器的一些信息
文章目录
ECM
在 HTML 中,JavaScript 代码必须位于 <script> 与 </script>
标签之间。
使用外部脚本<script src="path"></script>
单行注释:// 多行注释/**/
标识符:首字符必须是字母、下划线或美元符号($)。
字符集:JS用Unicode字符集。
代码块:语句可以用花括号{…}组合在代码块中
- JavaScript 能够以不同方式“显示”数据:
- window.alert() 写入警告框
- document.write() 写入 HTML 输出,(仅用于测试,会覆盖当前HTML内容)
- innerHTML 写入 HTML 元素
- console.log() 写入浏览器控制台
访问 HTML 元素,JavaScript 可使用 document.getElementById(id)
方法。
innerHTML 属性定义 HTML 内容
控制台(Console)使用:打开开发者工具(F12)后,我们可以在 Console 窗口调试 JavaScript代码
snippets小脚本:开发者工具中Sources面板选择Snippets,可以创建脚本文件,在右侧输入代码保存Ctrl+S。
变量及作用域
使用var声明变量:var person = "Bill Gates", price = 15000;
不带有值的变量,它的值将是 undefined。
严格模式:在脚本或函数开头添加"use strict;"
把之前可接受的“坏语法”转变为真实的错误。(如变量必须先声明,删除delete变量/函数等是不允许的)
作用域:全局作用域、函数作用域、块作用域
var | let、const(块作用域变量) |
---|---|
在块内定义的变量,块外也可以访问 | 块内定义的变量,块外不可访问(比如for循环块使用let i=0) |
定义的全局变量属于windows对象windows.variable | 定义的全局变量不属于windows对象 |
变量声明(初始化后不能提升)会得到提升(先使用后声明), | 变量必须先声明后使用 |
const:必须在声明时赋值,且不能重新赋值,但可以更改,更改≠赋值
// 创建 const 对象/数组
const car = {type:"porsche", model:"911", color:"Black"};
const che = ["Audi", "BMW", "porsche"];
// 可以更改或添加属性:
car.color = "White"; car.owner = "Bill";
cars[0] = "Honda"; cars.push("Volvo");
同一作用域,var、let、const声明后不能互相改变,如:var x; let x;
运算符
===:数据类型和值都相等 >= <=
!==:不完全相等 ++,–:自增自减
/:真正意义的除法 &&,||:逻辑与/或
条件运算符: (condition)?v1:v2 **:幂
+:字符串+数字,返回字符串var y = "7" + 8; //y为78
类型运算符:typeof返回变量类型;instanceof如果对象是对象类型的实例,返回 true
位运算符:
字符串与数字比较时(<,>,==……),会把字符串转为数字,空串为0,非数值字符串为NaN(比较结果必为false)
正则表达式
正则表达式是构成搜索模式(search pattern)的字符序列,可用于执行所有类型的文本搜索和文本替换操作。
语法:/pattern/modifiers;
- 修饰符modifiers
- i:不区分大小写
- g:全局搜索
- m:执行多行匹配
- 字符集:
- [abc]:就是任意多个字符进行集合书写,某一个进行匹配。
- [0-9],[A-Z],[a-z]、[0-9a-zA-Z]:范围中的某一个
- (x|y)
- 元字符
- \d:查找数字,等同于[0-9] \D:非数字
- \s:找空白字符 \S:非空格
- \w:字母数字或下划线 \W
- \b:匹配单词边界
- \uxxxx:查找十六进制数xxxx规定的Unicode字符
- 定义量词
- n+:匹配至少包含一个n的字符串
- n*:匹配包含n的字符串
- n?:匹配包含0或1个n的字符串
- 边界符
- ^:字符串必须以^后面的内容作为开头
- $:字符串必须以$前面的内容作为结尾
//元字符
var reg=/a\s+b/i //reg为"a b" 且a,b不区分大小写
//字符集[]
var str1="我喜欢张靓颖和张碧晨的歌"
var index1=str1.match(/张[靓碧][颖晨]/);
var str2="12306,11111";
var index2=str1.match(/[0-9]+/);
//边界符^、$
var reg2=/^ab/i, reg3=/ab$/i;
test()返回true/false
/e/.test("Freedom!");
数据类型
var length = 7; // 数字
var lastName = "Gates"; // 字符串
var cars = ["Porsche", "Volvo", "BMW"]; // 数组
var x = {firstName:"Bill", lastName:"Gates"}; // 对象
可以使用关键字new声明变量类型。如var carname=new String;
-
typeof 返回数据类型
string、number、boolean、undefined
function、object(对象/Array/null/Date)
- 基本数据类型存储在栈空间——数值
引用数据类型存储在堆空间——地址
- 基本数据类型存储在栈空间——数值
JS全局方法(适用于所有数据类型) | 描述 |
---|---|
Number() String() | 返回数字。若无法转换返回NaN 任意类型转字符串 |
parseFloat() | 参数转浮点数,只返回首个数字,且字符串首位是数字。否则无法转换,返回NaN |
parseInt() | 参数转整数 |
①Number数字
JavaScript 数值始终以双精度浮点数double来存储,即64位。
var n1= 7, n2=7.0, n3=7e-5, n4=7E5,n5=0xFF;
//精度:整数(不使用指数或科学计数法)会被精确到15位
var x=1234567899999999 //x:123456790000000
//小数最大17位,使用toFixed()控制小数位数
var x = 0.2 + 0.1; // x 将是 0.30000000000000004
//改变进制toString()
var myNumber = 128;
myNumber.toString(16); // 返回 80
-
特殊值:
-
NaN(Not a Number非数值),isNaN(),
-
Infinity:正无穷,
-Infinity
:负无穷 -
数字属性:用法
Number.MAX_VALUE
/Number.MIN_VALUE
-
toExponential() | 以指数形式表示数字9.66e+0 参数可选,为保留小数的位数 |
---|---|
toFixed() | 指定几位小数 |
toPrecision() | 指定数字长度 |
toString() | 转字符串型。参数可选,以基数 2 到 36改变数字进制 |
②String字符串
var animal= "It's a so-called \"dog\".";
可以通过转义字符\
添加引号
特殊:纯数字字符串可以像数字类型进行运算。
字符串长度length属性:str.length
字符串只能替换不能更改,所有方法只是返回新字符串
var str="hell" str[0]="A";//不报错但没用,不会改变str
-
indexOf():返回字符串中指定文本***首次***出现的索引(位置)
lastIndexOf() :返回指定文本在字符串中***最后***一次出现的索引
-
参数二:检索的起始位置。lastIndexOf从起始位置向前检索(包括起始位置所在的文本)
-
如果没找到,indexOf() 和 lastIndexOf()均返回 -1。
-
var str = "The People's Republic of China is called China for short.";
var pos = str.indexOf("China");
var lastPos=str.lastIndexOf("China");
-
拼接字符串:concat()
//下面两行是等效的: var text = "Hello" + " " + "World!"; var text = "Hello".concat(" ","World!");
-
提取部分字符串:
-
slice(start,end):
- 返回下标为start到end-1部分的字符串。
- 如果某个参数为负,则从字符串的结尾开始计数。
- 参数二end可以省略。
-
substring(start,end)
和
slice()
类似,但不支持负索引 -
substr(start,length)
-
toUpperCase() toLowerCase() | 大小写转化 |
---|---|
trim() | 删除字符串两端空白符 |
includes(value,start) | 若字符串包含value,返回true。参数二可选 |
charAt() | 返回下标处的字符,找不到返回空串 |
charCodeAt() | 返回下标处字符的Unicode编码 |
startsWith(value,start) | 若以指定值开头,返回true |
endsWith(value,length) | 前length个字符如果含value,返回true。参数二可选 |
可以结合正则的字符串方法:
- 字符串转为数组
split()
var str = "aa b ccc d e f";
var arr = str.split(/\s+/); //[aa,b,ccc,d,e,f]
如果split("")
,返回的数组元素都是单个字符;
分隔符任意,符号字符都行
split()中的分隔符如果不是字符串中元素,返回只有一个元素的数组,这一个元素就是整个字符串。
-
search()
:和indexOf作用相等,返回第一个符合条件的子串的下标。但search只有一个参数;indexOf无法使用正则表达式,search可以。 -
replace()
:替换字符串内容
var str="wa with water is still water"
var n= str.replace("fire", "water");
var m= str.replace(/Fire/gi,"water");//正则表达式/i:设置不区分大小写;/g,替换所有。
replace()并不会改变原字符串,只是返回新的字符串,且replace()只替换首个匹配项
通过replace给String添加函数方法
if (!String.prototype.trim) {
String.prototype.trim = function () {
return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
};
var str = " Hello World! ";
alert(str.trim());
str.match(sonStr)
:在str中搜索sonStr,找到则以数组形式返回,只返回一个,找不到返回null
var str2 = "aaaa o o bbb o o aaa";
//匹配所有"o o"的字符串
var arr2 = str2.match(/o\s+o/g);
③Array数组
//法一********
var cars=["Saab","Volvo","10000"];
var cars=[];
//法二,没必要用new Array(),知道就好
var cars=new Array("Saab","Volvo","BMW");
var cars=new array();
typeof 返回”object“,通过Array.isArray()
判断数组
添加数组元素:push()
或直接赋值
创建高索引的元素会在数组中产生未定义undefined
var fruits = ["f1","f2","f3"];
fruits[5] = "f5"; // 向 fruits 添加一个新元素 (f5)
//此时fruits[4]就是undefined
数组方法 | 描述 |
---|---|
toString() | 转为以逗号分隔数组元素的字符串 |
join() | 转一条字符串。参数:规定分隔符 |
pop() | 删除并返回最后一个元素 |
push() | 数组末尾添加新元素,返回新数组长度 |
shift() | 删除并返回首个元素(剩余元素前移) |
unshift() | 数组开头添加元素(原有元素后移),返回新数组长度 |
concat() | 合并数组array1.concat(array2,array3) |
slice(start,end) | 返回start到end-1元素组成的数组 |
reverse() | 反转数组 |
splice(参1,参2,添加元素)
参1:添加元素的位置
参2:在(参1)位置开始删除(参2)个元素
添加元素(可选):下标即为(参1),可不止一个
-
数组排序:
- 字符串排序:sort()
- 数字排序:插入比较函数
sort(function(a, b){return a - b});//从小到大排序 sort(function(a, b){return b - a});//从大到小排序
-
查找数组最值:
Math.max.apply(null, arr);
Math.max(...arr);
Math.min.apply(null, arr);
Math.min(...arr);
-
数组迭代
-
forEach(value,index,array)
:每个数组元素调用一次函数var numbers = [45, 4, 9, 16, 25]; numbers.forEach(myFunction); function myFunction(value) { value ++ ; }
-
map(value,index,array)
:对每个有值数组元素执行函数,以创建新数组,不会更改原始数组var numbers1 = [45, 4, 9, 16, 25]; var numbers2 = numbers1.map(myFunction); function myFunction(value) { return value * 2; }
-
filter(value,index,array)
过滤器,过滤后的元素组成新数组var numbers = [45, 4, 9, 16, 25]; var over18 = numbers.filter(myFunction); //myFunction:返回true保留,false过滤 function myFunction(value, index, array) { return value > 18; }
-
indexOf()
和lastIndexOf()
-
④Object对象
//对象属性(键值对) name:value
var person={firstname:"John", lastname:"Doe", id:5566};
//寻址方式
person.lastname;
person["lastname"];
访问对象方法
objectName.methodName(); //调用对象方法
objectName.methodName; //返回函数定义
//方法实际上是以属性值的形式存储的函数定义。
避免将字符串、数值、布尔值声明为对象!
//以下会增加代码的复杂性并降低执行速度
var x = new String(); // 把 x 声明为 String 对象
var y = new Number(); // 把 y 声明为 Number 对象
var z = new Boolean(); // 把 z 声明为 Boolean 对象
- Date对象
- new Date()
- new Date(year, month, day, hours, minutes, seconds, milliseconds)
JavaScript 从 0 到 11 计算月份。month大于11时,会进位到year
toDateString()
方法将日期转换为更易读的格式
- Math
- 绝对值abs()
- pow(x,y),sqrt(x)
- random:返回0~1之间的随机数
- min,max(n1,n2,n3……)
⑤函数
function 函数名(形参1,形参2){}
functionName 引用的是函数对象,返回函数定义;
functionName() 引用的是函数返回值。
arguments——类数组对象
只存在于函数体中,是object类型;只能用数组的length属性和访问方式。
作用:在函数没有形参的情况下,获取实参
function hanshu(){
var sum=0;
for(let i=0;i<arguments.length;i++){
sum+=arguments[i];
}
}
fun(1,2,3,4,5,6);
箭头函数:
hello = () => {
return "Hello World!";
}
//如果箭头函数只有一个语句且返回一个值,可以去掉括号和return
hello = () => "Hello World!";
//如果有参数,则将它们传递到括号内:
hello = (val) => "Hello " + val;
箭头函数没有对this的绑定,this指向箭头函数的”所有者“,定义箭头函数的对象,全局是window对象
⑥未定义(Undefined):没有值的变量,其值为undefined。
任何变量均可通过设置值为 undefined
进行清空。
⑦Null:
在 JavaScript 中,null 的数据类型是对象Object。
通过设置值为null
来清空对象
typeof undefined // undefined
typeof null // object
//Undefined与null值相等,但类型不同
null === undefined // false
null == undefined // true
⑧布尔型(Boolean): 只有true和false两个值
“”、undefined、null、NaN的布尔值都是false
条件和循环语句
条件语句 if…else if…else、switch(和C++用法一样)
- 循环:
- for(语句 1; 语句 2; 语句 3):遍历代码块
- while和do/while
- for/in:遍历对象属性,更适合(name:value)型的对象,遍历不是严格顺序,故数组慎用。
var person = {fname:“Bill”, lname:“Gates”, age:62};
for(let x in person) { //typeof x:object
console.log(person.x);
}
var Tom=[18,“男”,180,“70kg”];
//以下两个for实现效果相同
for(let i in Tom){ //typeof i:string
console.log(Tom[i]);
}
for(let x of Tom){ //typeof x:object
console.log(x);
}
- for(variable of iterable):遍历**可迭代对象**的值(数值,数组,字符串,映射set,map等有迭代器对象的)
```js
let language = "JavaScript",text = "";
for (let x of language) {
text += x;
}
## 错误
| try | 使您能够测试代码块中的错误。 |
| ------- | ---------------------------------------- |
| catch | 允许您处理错误(try代码块发生错误时) |
| throw | 抛出错误(可以创建自定义错误) |
| finally | 在 try 和 catch 之后,无论结果如何都执行 |
JavaScript 会创建**Error 对象**,带有两个属性`name`和 `message`。
name:错误的名称(如ReferenceError、SyntaxError、TypeError、RangeError)
message:错误的具体信息(如adddlert is not defined)
```html
<!DOCTYPE html>
<html>
<body>
<p>请输入 5 - 10 之间的数字:</p>
<input id="demo" type="text">
<button type="button" onclick="myFunction()">测试输入</button>
<p id="message"></p>
<script>
function myFunction() {
var message, x;
message = document.getElementById("message");
message.innerHTML = "";
x = document.getElementById("demo").value;
try {
if(x == "") throw "空的";
if(isNaN(x)) throw "不是数字";
if(x < 5) throw "太小";
if(x > 10) throw "太大";
x = Number(x);
}
catch(err) {
message.innerHTML = "输入是 " + err;
}
finally {//清空输入框
document.getElementById("demo").value = "";
}
}
</script>
</body>
</html>
模板字面量(Template Literals)
使用反引号 (``)而不是引号包围字符串
字符串插值${}
:用真实值自动替换变量
let price = 10;
let VAT = 0.25;
let total = `Total: ${(price * (1 + VAT)).toFixed(2)}`;
例:HTML模板
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
</body>
</html>
<script>
let header = "Templates Literals";
let tags = ["template literals", "javascript", "es6"];
let html = `<h2>${header}</h2><ul>`;
for (const x of tags) {
html += `<li>${x}</li>`;
}
html += `</ul>`;
document.getElementById("demo").innerHTML = html;
</script>
类
类不是对象,只是对象的模板
class ClassName {
constructor() { ... }//构造函数
//添加class方法
method_1() { ... }
method_2() { ... }
method_3() { ... }
}
实例:
class ClassName {
//构造函数可以自行修改,带入参数
constructor(name, year) {
this.name = name;
this.year = year;
}
age() {
let date = new Date();
return date.getFullYear() - this.year;
}
}
// 通过类创建对象
let myCar1 = new Car("Ford", 2014);
var x=myCar1.age(); //x=2022-2014=8
DOM
通过 HTML DOM,JavaScript 能够访问和改变 HTML 文档的所有元素。
当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)
在DOM中,所有HTML元素(标签)都被定义为对象
DOM属性:
//documentElement:获取到<html></html>内的源代码
console.log(document.documentElement);
//head:获取到head标签内的源代码
console.log(document.head);
//title:获取到title标签中的文本
console.log(document.title);
//body:获取到body标签内的源代码
console.log(document.body);
获取及操作节点
获取节点(标签)对象:
-
getElementById()
-
getElementsByTagName():通过标签名获取节点,返回类数组(arr.lenth和arr[i])
-
getElementsByClassName()
-
querySelector():通过选择器获取节点,仅返回匹配到的第一个节点。
如querySelector("div ul li")
-
querySelectorAll():获取所有节点,返回类数组
操作节点属性:
<div id="box" class="cur"></div>
……
var div = document.getElementById("box");
//获取节点属性值
console.log(div.id);
console.log(div.className);
//更改节点属性值
div.id="BOX";
div.className="CUR";
操作节点文本:
- 操作表单元素:通过value属性
- 操作非表单属性(非input标签即可):通过innerHTML属性
操作节点样式:
var p = document.getElementById("box");
//获取行内样式
console.log(p.style);
console.log(p.style.width);
//设置样式样式
p.style.width = "200px";
p.style.height = "200px";
p.style.backgroundColor= "cyan";
background-color、font-size等等中间带”-“的变为驼峰写法backgroundColor,fontSize
事件绑定
HTML 事件是发生在 HTML 元素上的“事情”。当在 HTML 页面中使用 JavaScript 时,JavaScript 便能够“应对”这些事件。
只要标签才能绑定事件
语法:<element event="一些 JavaScript">
或element.onxxxx=function(){}
在下面的例子中,onclick
属性(以及代码)被添加到 <button>
元素:
//通过标签属性分配事件
<button onclick="XSdate(this)">现在的时间是?</button>
function XSdate(bq){
bq.innerHTML=Date();
}
//向标签指定事件
<button id="myBtn">显示事件</button>
var btn=document.getElementById("myBtn");
btn.onclick = function(){
this.innerHTML=Date();
}
- 鼠标事件
- onmousedown;onmouseup;onclick;构成完整鼠标点击事件
- 单击:onclick 双击:ondblclick
- 鼠标悬停与移出:
- onmouseover onmouseout:移到子元素上也会触发
- onmouseenter onmouseleave:只有移到自身才会触发,而子元素不会
- 鼠标移动事件:onmousemove
- 常见的HTML事件
- onchange:HTML元素改变
- onkeydown:按下键盘
- onload:浏览器完成页面加载
- onfocus:输入框被点击 onblur:点击输入框以外区域
批量添加事件
- IIFE可以实现作用域的隔离,将变量函数等的定义隔离封装
var liArr=document.getElementsByTagname("li");
for(var i = 0 ; i < liArr.length;i++){
+function(index){
liArr[index].onclick = function(){
liArr[index].style.color = "red";
}
}(i);
}
/*
+function(){}()效果等于
(function(){})();或(function(){}());
*/
- this
for(var i = 0 ; i < liArr.length;i++){
liArr[i].onclick = function(){
this.style.color = "red";
}
}
事件对象
当用户触发事件的时候,系统会自动给事件处理函数传递实参,而这个参数即为事件对象(事件对象给我们传递很多信息)。
-
获取鼠标位置
- screenX,screenY:鼠标相对电脑屏幕的位置
- pageX,pageY:鼠标相对网页主题部分的位置(若有滚动条向下,这两值也会继续增大)
- clientX,clientY:鼠标相对网页可视区域的位置
- offsetX,offsetY:以所在盒子的左上角为参考,返回鼠标的位置。(鼠标若在父盒子之内,子盒子之外,则以父盒子为参考;在子盒子内,则以所在子盒子为参考)
-
拖拽
- 鼠标按下→鼠标移动→鼠标抬起
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
*{
margin:0;
padding: 0;
}
div{
/*定位元素才有left、top概念*/
position: absolute;
width: 200px;
height: 200px;
background: url("./images/0.jpg");
/*背景图尺寸大小*/
background-size: 200px 200px;
background-color:red;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
<script>
var div = document.querySelector('div');
//鼠标按下
div.onmousedown = function(event){
//短路语法兼容事件对象
var e = event||window.event;
//获取鼠标距离元素左侧顶部数据
var startX = e.offsetX;
var startY = e.offsetY;
//鼠标在整个网页中移动
document.onmousemove = function(event1){
var e1 = event1||window.event1;
//元素进行拖拽
div.style.left = e1.clientX - startX +"px";
div.style.top = e1.clientY - startY +"px";
}
}
//鼠标抬起事情----将鼠标移动事件移除
document.onmouseup =function(){
document.onmousemove = null;
}
</script>
BOM
BOM:浏览器对象类型,即浏览器内置的window对象,提供获取浏览器信息的属性、方法等
console.log(window);
console.log(window.location.href); //获取地址栏信息
console.log(window.screen.width,window.screen.height);//获取屏幕宽高
//window可以省略
alert(); //警告框
prompt(); //提示框,返回用户输入的数据
Timing事件
以指定的时间间隔执行代码,这些时间间隔称为定时事件。
-
setTimeout ( function, milliseconds):等待指定时间后执行函数(仅一次)
clearTimeout (timeroutVariable)
-
setInterval ( function, milliseconds)
clearInterval ( timerVariable )
var time = setInterval(myTimer, 1000);
//每隔一秒打印一次时间
function myTimer() {
var d = new Date();
document.querySelector("p").innerHTML = d.toLocaleTimeString();
}
//停止执行
clearInterval(time);