js速成基础

认识 JavaScript

1
2
3
网页开发三大核心之一
HTML(骨架) + CSS(衣服) + JavaScript(动作)
用途广泛:前后端开发、手机app开发、pc端应用程序开发

最基本的概念

1
2
3
4
5
6
7
8
(复习:
解释型语言:将源代码翻译为机器码进行执行,执行速度慢
编译型语言:将源代码编译为可执行文件,直接运行可执行文件,运行速度快)
js 是解释型语言,但做了非常多的优化,相比其他解释型语言性能较高
就像 Python 解释器,js 也依赖于 JavaScript 引擎进行运行

为什么不叫 JavaScript 解释器?
因为采用了一些其他的技术进行优化,不能简单的归类为解释型语言

V8 引擎

1
2
3
4
5
6
7
8
9
10
11
12
13
在学习过程中,我们会接触两个东西:
1. 谷歌浏览器内核
打开浏览器访问一个网页,就会运行 js 代码
这个时候的代码是利用谷歌浏览器内核进行运行的
2. node.js
不需要依赖浏览器,使用 node 解释器进行运行

两者都是在 V8 引擎的基础上进行实现的
也就是说:
1. 实际上我们只需要有 V8 引擎就能执行 js 代码
2. 谷歌内核和 node 只是在 V8 的基础上提供了一些内置对象给你进行使用
3. 两者的用途不同,提供的内置对象也不一样
4. 现在不懂没关系,后面会再回过头来复习

在谷歌浏览器内核环境运行 js 代码

1
2
3
4
5
edge 和 国内一些浏览器使用的都是谷歌的内核,但都会做一些修改,建议使用谷歌浏览器
1. 通过 HTML 运行
内嵌式:在 script 标签中编写 js 代码
外链式:通过 script 标签的 src 属性引入 js 文件
2. 使用控制台或临时脚本

在 node.js 环境运行 js 代码

1
2
3
4
5
6
1. 安装 node.js
下载链接:https://nodejs.org/zh-cn
安装教学:https://blog.csdn.net/Nicolecocol/article/details/136788200

2. 安装代码编辑器,需要专业版 pycharm
下载链接:https://www.jetbrains.com/zh-cn/pycharm/

ES 语法标准

1
2
3
4
5
6
7
8
规定了 JavaScript 的语法标准
JavaScript 引擎需要实现这些标准(比如需要有整数类型和字符串类型数据,类似这样的规定)
所以世界上其实有很多由不同的人实现的 JavaScript 引擎,V8 只是最常用的一个

ES 语法标准经历过数次更新
目前最新的标准为 ES6,2015 年更新
后续也有很多更新的版本,但更新内容不大,也不是非常必要
了解下即可,现在 ES6 标准已经普及了

打印

1
console.log,等价于 print

定义变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var:
可重复声明
默认值为 undefined(代表未定义,可理解为 py 中的 None)
变量提升(可以在声明前访问变量,值为 undefined)
函数作用域(在函数内使用 var 声明的变量,只在当前函数内可用)

let(ES6):
不能重复声明
不会变量提升
块级作用域(仅在当前代码块(大括号)中可以访问)

const(ES6):
不能重复声明
值不能修改
块级作用域

定义未声明变量:
全局作用域

严格模式

1
2
3
4
5
在 js 文件开头写上:
"use strict";
会启用严格模式,严格模式下:
1. 不允许定义没有经过声明的变量
2. this 默认指向 undefined

算术运算符

1
2
3
4
5
6
7
加减乘除、取余
+=

a++,等价于 a += 1
a++:先得到a,再加1
++a:先加1,再得到a
a--,等价于 a -= 1

比较运算符

1
2
3
==,比较值是否相等
===,比较值和类型是否相等
!=,!==

逻辑运算符

1
2
3
&&,等价于 and
||,等价于 or
!,等价于 not

数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
整数、浮点数(Number)、布尔(Boolean,true 和 false)

null:代表空值(通常手动赋值),转为布尔类型表现为 false
undefined:代表未定义(默认值),转为布尔类型表现为 false
NaN:数字类型,代表无效的数字,转为布尔类型表现为 false

类型转换:
比如:Number('1')
转浮点数:parseFloat
转整数:parseInt

字符串(String):
length 属性,获得长度
(可以取索引,但不能使用负数和切片,索引越界也不会报错)
slice 方法,切片,只有两个参数
includes 方法,判断是否包含某个字符,在较新的 ES 标准中添加
indexOf 方法,判断是否包含某个字符,并返回索引
split 方法,同 py
replace 方法,只会替换第一个匹配的
replaceAll 方法,同 py replace,在较新的 ES 标准中添加
格式化字符串(ES6):`Hello ${name}`

数组(Array):
可以包含不同类型类型数据(同 py)
length 属性,获得长度
push 方法,添加元素
(可以取索引,但不能使用负数和切片,索引越界也不会报错)
slice 方法,切片,只有两个参数
includes 方法,判断元素是否存在于数组中,在较新的 ES 标准中添加
indexOf 方法,得到相等的第一个元素在数组中的索引,没有则返回 -1
concat 方法,合并两个数组,不能像 py 使用加法运算
join 方法,同 py 字符串的 join 方法

对象(Object):
js 没有字典,使用对象进行代替
我们定义的对象都是 Object 类的实例对象(几乎所有对象都是 Object 类的实例对象)
Object.keys 方法,返回对象的所有属性名称
Object.values 方法,返回对象的所有属性值
取不存在的属性值时,不会报错
判断两个对象是否相等时,判断的是内存地址是否相等,而不是值
取属性有两种方式:
obj.attr
obj["attr"]

typeof:
用于得到数据类型,写法:typeof a
typeof null; // "object"(历史遗留 bug)
null === a,判断一个变量是否是 null
typeof [1, 2]; // "object"(无法区分数组和普通对象)
Array.isArray 方法:判断参数是否是数组
typeof NaN; // "number"(无法区分无效数字)
Number.isNaN 方法:判断参数是否是 NaN

加法运算:
数字 + 数字
数字 + 布尔、null,右侧被转为数字
数字 + undefined,undefined 被转为 NaN
数字 + 对象,会使用对象的 valueOf 方法的返回值进行计算,类似 py 类中的魔法方法(如 __len__)
字符串 + 字符串
字符串 + 任意类型,右侧被转为字符串
字符串 + 对象,会使用对象的 toString 方法的返回值进行计算

条件判断

1
2
3
4
5
6
7
8
9
10
11
if (条件) {
条件为真时执行
} else if (条件2) {
条件2为真时执行
} else {
以上条件都为假时执行
}
和 py 最大的区别是用大括号代表 py 中的缩进
没有 elif 关键字
条件需要放在括号中
简写:如果 条件为真时执行 只有一行代码的话,可以省略大括号

三元表达式

1
2
条件 ? 条件为真时执行并返回 : 条件为假时执行并返回
三元表达式可以嵌套很多层,可读性非常差,真实的开发中不会有人这样做

while 循环

1
2
3
4
5
6
7
8
9
while (条件) {
条件为真时循环执行
}
先判断,再循环

do {
至少执行一次的循环体
} while (条件)
先循环,再判断

for 循环形式一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
for (定义变量; 条件; 改变变量) {
条件为真时循环执行
}
for (循环开始时执行一次; 条件(每次循环开始前执行一次); 每次循环结束后执行一次)

所以以下的写法基本上都是等价的:
for (let i = 0; i < 5; i++) {
console.log(i);
}

let i = 0;
for (; i < 5; i++) {
console.log(i);
}

let i = 0;
for (; i < 5; ) {
console.log(i);
i++;
}

let i = 0;
while (i < 5) {
console.log(i);
i++;
}
可以看出这种形式的 for 循环和 while 循环基本没有区别

for 循环形式二

1
2
3
4
5
for (let i of 可迭代对象) {}
等价于 py:for i in 可迭代对象:

可迭代对象只是一种叫法,比如数组
但 js 中没有字典,对象也不能直接遍历

for 循环形式三

1
2
3
4
5
6
for (let i in 对象) {}

这种形式是专为对象准备的,用于遍历对象的所有属性名称
其实也可以用下面的方式实现,区别在于前者性能稍微好一些:

for (let i of Object.keys(对象)){}

函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
定义函数,必须指定名称:
function get_name() { 函数体 }

定义匿名函数,赋值给一个变量:
get_name = function (){}

参数传递:
传递少了不会报错,而是参数值为 undefined
传递多了也不会报错

函数也是一个对象,拥有一些内置属性和方法

函数的属性方法:
length 属性,得到参数个数
name 属性,得到函数名称
toString 方法,转为字符串形式

arguments 对象:
在函数中取 arguments,可以得到调用函数时传递的所有参数

自执行函数:
(function (){})()

箭头函数(ES6):
写法一,类似 py 中的 lambda 函数:
(参数) => 返回值
写法二,类似一个普通的匿名函数:
(参数) => { 函数体 }

异常处理

1
2
3
4
5
6
7
try {} catch (e){}
等价于 py 中的:
try: except Exception as e:

throw new Error("");
等价于 py 中的:
raise Exception("")

逗号表达式

1
2
用逗号连接多个语句,这些语句能够被看作是一个逗号表达式,拥有一个返回结果
在一个语句中执行多个操作,返回最后一个表达式的结果

switch case

1
根据值跳转到指定代码

V8 常用对象和函数

1
2
3
4
5
6
7
8
9
10
11
12
13
Date,时间相关对象
需要实例化
getTime 方法,获得 13 位时间戳,单位为毫秒,py 的时间戳是 10 位的,单位为秒
Math,数学相关对象
静态方法类,不需要实例化
random 方法,获得随机数
JSON
静态方法类,不需要实例化
stringify 方法,对象转 json 字符串
parse 方法,json 字符串转对象
(不属于 V8,但 node 和浏览器中都具备的常用函数)
setTimeout(func, time) 函数,指定毫秒过后执行指定函数
setInterval(func, time) 函数,每经过一次指定毫秒,执行一次指定函数

谷歌内核常用对象和函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
window:
全局对象(他的属性等同于全局变量,全局变量等同于他的属性)
navigator:
浏览器信息对象
userAgent 属性,浏览器版本等信息
platform 属性,平台
location、screen 等
document:
HTML 文档对象
getElementsBy... 方法,获得页面中的标签对象
querySelector 方法,根据 CSS 选择器获得标签
createElement 方法,创建一个标签对象
对于单个标签对象:
getAttribute 方法,获得属性值
setAttribute 方法,设置属性值
appendChild 方法,添加子标签
innerText 属性,标签内的文本
innerHTML 属性,标签内的 HTML 文本
addEventListener(事件类型, func) 方法:
指定类型事件触发时,调用指定函数并通过参数传递相关信息

node.js 常用对象和函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
global:
全局对象(他的属性等同于全局变量,全局变量等同于他的属性)
process:
argv 属性,得到命令行调用时传递的参数
exit 方法,强制结束当前进程
require 函数:
导入模块
没有自动补全提示:
打开 Pycharm 终端,执行命令:
npm install --save-dev @types/node
如果报错可能存在权限问题,将 node 安装路径下的 node_cache、node_global、node_modules 文件添加完全控制权限
右键文件夹 -> 属性 -> 安全 -> 编辑 -> 勾选完全控制
下载慢:
更换淘宝源: npm config set registry https://registry.npmmirror.com

使用第三方模块

1
2
3
4
5
6
7
8
9
10
11
12
浏览器环境:
通过外链式 script 标签导入
node 环境:
通过 npm install xxx 命令安装,require 函数导入
安装模块后会在当前路径下生成一个 node_modules 文件夹,存放你安装的模块
导入模块时会从当前目录开始,不断向上寻找这个文件夹,并尝试找到你需要的模块
通过 npm install -g xxx 命令全局安装
模块会被安装到 node 安装路径下的 node_modules 文件夹
下载慢:
更换淘宝源: npm config set registry https://registry.npmmirror.com
如果报错可能存在权限问题,将 node 安装路径下的 node_cache、node_global、node_modules 文件添加完全控制权限
右键文件夹 -> 属性 -> 安全 -> 编辑 -> 勾选完全控制

常用第三方模块

1
2
3
4
5
6
7
8
9
10
11
浏览器,jQuery:
使用 $ 符号按 CSS选择器语法 选取页面元素,如:$("#id")
$.ajax({ // 发送请求
url: "链接",
type: "get",
data: { 请求参数 },
success: function (res){ 当成功得到响应后,立刻执行该函数 }
});

node,express:
npm install express

闭包

1
2
3
4
5
创建一个封闭的内存空间(变量空间、命名空间),只有指定函数可以访问该空间内的变量
一个函数就是一个闭包,一个函数内的函数就是可以访问该空间内变量的指定函数

用处就是创建一个命名空间,防止意外使用了相同的变量名
或者用于在面向对象中模拟一个私有属性

面向对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
JavaScript 的面向对象非常随意(灵活)
不要用其他语言面向对象的思维去理解
不学 class 关键字,只是做了点封装,本质上还是下面的方式

使用 function 关键字定义类的构造函数
this 关键字
使用 new 关键字实例化时,this 指向新的实例对象,等价于 py 中的 self
this 默认指向全局对象
作为对象的方法被调用时,this 指向该对象
箭头函数不会有自己的 this

prototype 属性得到函数的原型
实例对象会拥有类的原型上的属性方法(并不是实例对象直接拥有,而是当实例对象自身没有时,会去原型中拿)
可以理解为:定义类属性(静态属性,每个实例共享)需要在原型上定义
每个实例对象都会有 __proto__ 属性,指向函数的 prototype

原型链:
函数的原型就是一个 Object 类的实例对象,所以也拥有 __proto__ 属性
对象.__proto__.__proto__.__proto__...,这就是原型链
当取实例对象的属性时:
看实例对象自身有没有
没有就去原型链中找
这一层原型没有就去上一层原型找
这一层原型找到了那就直接用,不会再看上一层原型了
可用于实现继承

JavaScript 中,new 一个对象可以理解为就两个步骤:
1. 将新实例对象的 __proto__ 属性赋值为类的 prototype 属性
2. 执行构造函数
这些步骤可以通过 new 关键字实现,也可以手动

每个函数都会有 prototype 属性
每个实例对象都会有 __proto__ 属性
函数也是一个实例对象,所有同时拥有这两个属性
每个函数都是 Function 类的实例对象
Function 类的 prototype 是 Object 类的实例对象
可以通过直接赋值的方式创建实例对象(只拥有类属性)

instanceof 关键字:
判断左侧对象的原型链中是否存在右侧对象的原型

自定义 this 指向

1
2
3
4
5
6
第一个参数:要指向的自定义 this 对象

方法名 | 立刻执行 | 传递参数
apply | 是 | 列表
call | 是 | 按顺序
bind | 否 | 按顺序

Promise 异步

1