JS基础
JS基础知识,先速通一遍,以后再慢慢补充细节
引入方式
内部脚本
将JS代码定义在HTML中。可以在任意地方放置任意数量的js,但是一般会把脚本位于<body>
元素的底部,可以改善显示速度。
1 |
|
外部脚本
定义在外部js文件中,HTML文档通过以下格式引用,不能自闭合。外部js文件不需要<script>
1 |
|
基本语法
- 每行结尾的分号可有可无(但是建议加上)
- 输出语句
window.alert()
弹出窗口(/əˈlɜːrt/ 意思是警示)document.write()
写入HTML文档(开发很少用)console.log()
输出到控制台
变量
在 JavaScript 中定义变量的方法有三种,分别是
let
(推荐)
1 |
|
let
定义的是可以更改值的变量- 代码块内有效
const
(推荐)
1 |
|
const
定义的是常量,不能重新赋值- 一旦赋值就不能改变
- 代码块内有效
var
⚠️(不推荐)
1 |
|
- 旧语法(ES5之前),写老代码、或者兼容旧浏览器才用
- 允许修改
- 变量会提升(hoisting),且是函数作用域,容易出 bug
- 出代码块还可以访问,属于全局变量
- 可以重复定义,前两个都不行。例如
1 |
|
不报错。
数据类型、运算符、流程控制语句
数据类型
- 原始类型(Primitive Types)
对应Java中的基本数据类型,但是分得没那么细
数据类型 | 示例值 | 说明 |
---|---|---|
number |
42 , 3.14 , NaN ,
Infinity |
数字类型,包含整数和浮点数 |
string |
"Hello" , '世界' |
字符串,单双引号都可 |
boolean |
true , false |
布尔值 |
undefined |
let x; → x === undefined |
声明未赋值时的默认值 |
null |
let x = null |
表示“无”或“空值” |
bigint |
12345678901234567890n |
大整数类型(ES2020+) |
symbol |
Symbol("id") |
独一无二的标识符 |
- 引用类型(Reference Types)
对应Java中的引用数据类型,但是少得多
数据类型 | 示例 | 说明 |
---|---|---|
object |
{ name: "Miku", age: 16 } |
普通对象,键值对结构 |
array |
[1, 2, 3, "初音"] |
数组,JS 中是一种对象类型 |
function |
function greet() {} |
函数也是对象 |
date |
new Date() |
日期对象 |
regexp |
/abc/ , new RegExp("abc") |
正则表达式对象 |
使用typeof
运算符可以得到数据类型。
运算符
算术运算符,逻辑运算符同Java。
比较运算符:
1 |
|
赋值运算符: 1
2= **
+= -= *= /= %= **=
**
:指数运算符Exponentiation Operator),例如2**3
表示2的三次方。它是左结合运算符,比如2 ** 3 ** 2
的计算顺序是2 ** (3 ** 2)
。**=
是指数赋值运算符(Exponentiation assignment operator),ES7加入。举个例子:x **= y
,意思就是x = x ** y;
,意思就是把x的y次方赋给x本身。例如:
1 |
|
就是把a
的3次方赋值给a
,结果为8。
类型转换
转换成字符串
.toString()
Boolean值、数字(number)和字符串(string)都是伪对象,它们实际上具有属性和方法,.toString()
就是其中一种可供调用的方法。
另外number类型的toString()
方法比较特殊,如果不传入任何参数,那么采用的是默认模式,返回的是数字的十进制表示。如果传入参数,即为基模式,可以用不同的基(radix)输出数字。
例如,以下代码
1 |
|
得到的结果为1001
,也就是十进制数字9的二进制表示。
转换成数字
转换为整数:parseInt
转换为小数:parseFloat()
从开头开始从左到右读取是数字的部分。如果开头就不是数字,则转换失败,返回NaN
(Not
a Number)。
字符串中包含的数字字面量会被正确转换为数字,例如"0xA"会被转换成数字10。但是"22.5"会被转换成22,因为小数点被当成无效字符处理了。parseFloat()
会把遇到的第一个小数点当成小数点处理。
parseInt()
方法也有基模式,定义为parseInt(string: string, radix?: number): number
,但是parseFloat()
没有。
相比之下,Java使用Integer.parseInt()
Float.parseFloat
Double.parseDouble()
Long.parseLong
等方法进行转换,如果转换失败会抛出NumberFormatException
异常。
强制类型转换
type casting
cast有“铸造”之意,很贴合“强制转换”的意思
ECMAScript 中可用的3种强制类型转换:
- Boolean(value) - 把给定的值转换成 Boolean 型;空字符串、数字 0、undefined 或 null,返回 false。
- Number(value) - 把给定的值转换成数字(可以是整数或浮点数);处理整个值。
- String(value) - 把给定的值转换成字符串;
函数
使用function进行定义,语法为
1 |
|
- 形参不需要类型,因为js弱类型
- 返回值也不需要定义类型,有return就说明有返回值
- 调用的时候可以传递任意个数的参数
函数作为形参时,使用lambda表达式会舒服很多。
*闭包(closure)
引入
JS比较独特的一个特性。
JavaScript 变量属于 本地 或 全局 作用域。 全局变量能够通过 闭包 实现局部(私有)。
- 在网页中,全局变量属于
window
对象,全局变量能够被页面中(以及窗口中)的所有脚本使用和修改。 - 而局部变量只能用于其被定义的函数内部,对于其他函数和脚本代码来说它是不可见的。
考虑下面这种情况:我们想做一个计数器用来计数函数被调用的次数。如果使用下面这种方式
1 |
|
虽然能实现计数的功能,但是不够安全,因为作为全局变量的counter
可以被任意函数随意更改。为了防止随意更改,考虑把它声明为局部变量:
1 |
|
显然仍然存在问题,因为每次调用这个函数时都会给counter
重新赋值为0,不能实现计数的功能,我们必须保证初始化函数之被调用一次
在Java中,我们可以使用权限修饰符private
和getter
解决安全性问题,但是JS中没有权限修饰符,怎么办?有没有什么东西可以实现类似的功能?
答案是有的,那就是闭包。
使用
1 |
|
add
是外层函数,内部定义了一个内部匿名函数,并且add
的返回值就是内部函数的引用,或者说句柄;const conterFunc = add();
调用了一次外层函数,创建一个counter
并初始化为0;- 之后每次调用
conterFunc()
实际上调用的是内层函数,因为counter
还是第一次创建好的那个,所以可以正常计数; - 又因为
counter
是函数内部定义的局部变量,所以不会被外界访问到,足够安全。
注意:每次调用add()
会生成新的独立包,相互独立互不影响,所以只在开头调用了一次。
闭包还可以把多参数的函数变成单参数的函数,例如平方和立方的计算:
1 |
|
生成器(generator)
ES6标准引入的新的数据类型。另外,
生成器函数 是一种可以“暂停执行”的函数,通过 function* 定义,用 yield 控制流程,返回的是一个 可迭代对象(iterator)。
yield
: 返回一个值给外部,同时暂停函数的执行。next()
: 一旦调用就执行到下一个yield
调用这个函数不会直接执行函数体内部的代码,而是返回一个生成器对象(generator object)。每次调用它都会重开一个生成器。
为了让生成器能往下跑,需要采用类似闭包的方法:先获取句柄
1 |
|
对象
- Array
- String
- JSON
- BOM(Browser Object Model, 浏览器对象模型)
- DOM(Document Object Model, 文档对象模型)
包装类对象
1 |
|
别用
Date
1 |
|
JavaScript 从 0 到 11 计算月份。 一月是 0。十二月是11。 6个数字指定年、月、日、小时、分钟、秒:
Array
- 定义
1 |
|
- 访问
1 |
|
- 遍历:推荐
forEach
方法(相当于Java中的forEach+lambda表达式)
1 |
|
JS数组长度可变,类型可变,可以存储任意类型的数据。没有赋值的位置记为undefined。
属性:length
,用法同Java
方法:
forEach
:遍历有值的元素,并调用传入的函数push()
:将新的元素添加到数组的末尾,并返回新的长度splice(start: number, deleteCount?: number): number[]
:从数组中删除元素,左闭右开。问号表示可选参数
1 |
|
控制台:3 4
String
创建
1 |
|
属性:length
方法:
charAt(index)
:返回字符串中 指定位置的字符。indexOf(searchValue, fromIndex?)
:从fromIndex开始查找某个子字符串第一次出现的位置,找不到就返回 -1。trim()
:去除字符串两边的空格(不包括中间的空格)。substring(startIndex, endIndex?)
:截取字符串的一部分,左闭右开。
对字符串做一些补充
- 多行字符串:
1 |
|
通过反引号的形式声明多行字符串,可以省去换行字符。
- 模板字符串:
要把多个字符串连接起来,可以用+号连接;ES6新增了一种模板字符串,连接字符串更方便:(注意使用反引号包裹)
1 |
|
JSON
基于 JavaScript 语言的轻量级的数据交换格式(JavaScript Object Notation)
意义:
当数据在浏览器与服务器之间进行交换时,这些数据只能是文本。
JSON 属于文本,并且我们能够把任何 JavaScript 对象转换为 JSON,然后将 JSON 发送到服务器。
我们也能把从服务器接收到的任何 JSON 转换为 JavaScript 对象。
以这样的方式,我们能够把数据作为 JavaScript 对象来处理,无需复杂的解析和转译。
虽然名字里有 JavaScript,但它是语言无关的格式,可以被几乎所有语言(如 Python、Java、C#)支持。
先说说JS自定义对象:
1 |
|
如何定义一个JSON:
1 |
|
- 把 JSON
字符串转为对象:
const obj = JSON.parse(jsonStr);
- 把对象转为 JSON
字符串:
const jsonStr = JSON.stringify(obj);
面向对象编程
参看这位大佬的博客:
BOM
浏览器对象模型允许 JavaScript 与浏览器对话。
window
:窗口对象,去除占位符后的净宽高为(IE<=8不支持)innerWidth
innerHeight
screen
:表示屏幕的信息(宽,高,位宽)location
:当前页面的URL信息location.href
:当前页面的URLsetInterval
持续重复执行该函数。setTimeout
在等待指定的毫秒数后执行函数。
Cookie
浏览器用来存储小块数据(最多约 4KB)的一种机制。 它可以在用户浏览网页时,在本地保存数据,并在之后访问时自动携带到服务器。
我们登录了一个网站,关闭网页后第二天再来,不用重新登录了,就是因为Cookie。
DOM
当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)。
HTML DOM 模型被结构化为对象树:

通过document
对象的方法可以找到对象树上的节点,常用的有:
getElementById()
getElementsByTagName()
更新
获取对象后,可以对对象进行操作:
innerHTML
innerText
textContent
也可以修改css样式(和css的命名方式不一样)
.style.color
.style.fontSize
.style.paddingTop
格式:
1 |
|
插入
appendChild
insertBefore
## 删除
父节点调用removeChild
删除子节点
Async
回调
回调函数(Callback Function),将一个函数作为参数传递给另一个参数
JS事件
事件绑定的方式:
- 通过HTML中的事件属性。例如
<button onclick="displayDate()">试一试</button>
- 通过DOM分配事件,例如
1 |
|
*事件监听
在 JavaScript 中,事件监听(Event Listener) 是指你为一个 HTML 元素绑定一个函数(监听器),当某个事件发生时(比如点击、键盘输入、鼠标悬停等),这个函数就会被自动调用。
语法:
1 |
|
- 事件类型
- 事件发生时调用的函数
- 布尔值,指定事件是使用冒泡还是事件捕获,可选参数,默认是冒泡阶段(用得很少)
可以向一个元素添加多个事件处理程序。