基础
# JavaScript是什么
JavaScript
JavaScript(简称“JS”) 是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。虽然它是作为开发Web页面的脚本语言而出名,但是它也被用到了很多非浏览器环境中,JavaScript 基于原型编程、多范式的动态脚本语言,并且支持面向对象、命令式、声明式、函数式编程范式。
来自 百度百科 (opens new window)
特别感谢w3school (opens new window),以下知识点来源于w3school。
- JavaScrip版本 w3school (opens new window)
- JavaScrip历史 w3school (opens new window)
# 数据类型
基本类型
类型 描述 类型 描述 Number 数值 String 字符串值 Boolean 布尔值 Null 空值 undefined 未定义型 Object 对象 symbol() ES6
这种类型的对象永不相等,
即始创建的时候传入相同的值,
可以解决属性名冲突的问题,做为标记bigInt ES10
安全存储、操作大整数 引用数据类型
类型 描述 类型 描述 Object 对象 Array 数组 Function 函数 正则(RegExp) 特殊对象 日期(Date) 特殊对象 undefined和null区别
- undefined 与 null 的值相等,但类型不相等
- null类型是对象 undefined类型是undefined
复杂数据类型object
- function、 null、 Array、 Date()都是复杂数据类型
object
- function、 null、 Array、 Date()都是复杂数据类型
JavaScript 提供用于原始对象的构造器:
var x1 = new Object(); // 一个新的 Object 对象
var x2 = new String(); // 一个新的 String 对象
var x3 = new Number(); // 一个新的 Number 对象
var x4 = new Boolean(); // 一个新的 Boolean 对象
var x5 = new Array(); // 一个新的 Array 对象
var x6 = new RegExp(); // 一个新的 RegExp 对象
var x7 = new Function(); // 一个新的 Function 对象
var x8 = new Date(); // 一个新的 Date 对象
2
3
4
5
6
7
8
# 数值
NaN
属于 JavaScript 保留词,指示某个数不是合法数- isNaN() 来确定某个值是否是NaN
Infinity
是JavaScript 在计算数时超出最大可能数范围时返回的值。数字方法
- 变量转换为数值
方法 描述 Number() 返回数字 parseFloat() 返回浮点数 parseInt() 返回整数
# 数组
单一变量中存储多个值
创建数组的两种方式
- 数组字面量 var arr = [1,2,3]
- 数组构造函数 var arr = new Array(1,2,3)
数组方法
方法 描述 方法 描述 length 数组长度 forEach() 遍历数组 map() 遍历数组 filter() 过滤数组(不改变原数组) reduce() 归并类方法 every() 全部满足条件返回true some() 满足条件返回true find() 返回第一个满足条件的值 findIndex() 返回第一个满足条件的值的索引 includes(value,start) 检查数组是否包含指定的元素 indexOf() 查找元素值并返回其位置 lastIndexOf() 从数组结尾开始搜索 push() 后添加 unshift() 前添加 shift() 前删除 pop() 后删除 Array.isArray(值) 判断是否为数组(不支持老的浏览器) toString() 将数组转换为字符串(逗号分隔) join() 转换为字符串(指定分隔符) splice() 可添加新元素和删除元素 slice() 裁剪数组 concat() 数组连接 reverse() 翻转数组 sort() 数组排序(默认按字符串排序) Math.min.apply(null,arr) 最小值 Math.max.apply(null,arr) 最大值 map()与forEach()区别
- 参数都为item,index(索引),arr(原数组)
- 只能遍历数组
- map()会分配内存空间存储新数组并返回,forEach()不会返回数据
- forEach()允许callback更改原始数组的元素。map()返回新的数组
// 判断是否为数组方法
// 1. 通过对象原型包含单词 "Array" 判断为数组
function isArray(x) {
return x.constructor.toString().indexOf("Array") > -1;
}
// 2.由给定的构造器创建,instanceof返回true
arr instanceof Array
2
3
4
5
6
7
sort()数组排序
// 生序
arr.sort(function(a, b){return a - b});
// 降序
arr.sort(function(a, b){return b - a});
// 随机排序
arr.sort(function(a, b){return 0.5 - Math.random()});
// 数组中的对像进行排序(数值型)
arr.sort(function(a, b){return a.year - b.year});
// 数组中的对像进行排序(字符串)
arr.sort(function(a, b){
var x = a.type.toLowerCase();
var y = b.type.toLowerCase();
if (x < y) {return -1;}
if (x > y) {return 1;}
return 0;
});
// 最大值
function myArrayMax(arr) {
var len = arr.length;
var max = -Infinity;
while (len--) {
if (arr[len] > max) {
max = arr[len];
}
}
return max;
}
// 最小值
function myArrayMin(arr) {
var len = arr.length
var min = Infinity;
while (len--) {
if (arr[len] < min) {
min = arr[len];
}
}
return min;
}
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
# 字符串方法
方法 | 描述 |
---|---|
length | 返回长度 |
indexOf(value,index) | 文本首次出现的索引,index可设置为检索起始位置 |
lastIndexOf | 文本最后出现的索引 |
search() | 搜索特定值的字符串,返回索引 |
match(regexp) | 根据正则表达式在字符串中搜索匹配项,匹配项作为 Array 对象返回 |
includes(searchvalue, start) | 匹配成功返回true 否则为false |
startsWith(searchvalue, start) | 匹配成功返回true ,否则为false |
endsWith(searchvalue, length) | 匹配成功返回true ,否则为false |
slice(start, end) | 截取字符串开始到截取的值 如果某个参数为负,则从字符串的结尾开始计数 |
substring(start, end) | 截取字符串开始到截取的值(参数不为负) |
substr(start,length) | 第二个参数为截取的长度 |
replace() | 字符串替换 (只替换首个匹配 全局替换用正则 /name/g ) |
toUpperCase() toLocaleUpperCase() | 转换为大写 toLocaleUpperCase()根据本地主机的语言环境把字符串转换为大写 |
toLowerCase() toLocaleLowerCase() | 转换为小写 |
concat() | 连接两个或多个字符串 |
trim() | 删除字符串两端的空白符 |
charAt() | 返回字符串中指定下标 |
charCodeAt() | 返回字符串中指定索引的字符 unicode 编码 |
split() | 字符串转换为数组 (可根据, 、| 空格等分割) |
# 类型转换
- 转数字
- Number()
- parseInt() 会将小数取整
- parseFloat() 保留小数
- +str 将字符串转换为数字
- 转字符串
- String()
- toString()
- a + ''
- 转boolean类型
- Boolean()
- a = !!a
# 运算符
算术运算符
运算符 描述 运算符 描述 + 加法 - 减法 * 乘法 / 除法 ++ ++i 前自增运算符(先自增,在赋值)
i++ 后自增运算符(先赋值,后自增)-- --i 前自减运算符(先自减,在赋值)
i-- 前自减运算符(先赋值,后自减)% 取余 赋值运算符
运算符 例子 等同于 = x = y x = y += x += y x = x + y -= x -= y x = x - y *= x *= y x = x * y /= x /= y x = x / y %= x %= y x = x % y 比较运算符
运算符 描述 运算符 描述 == 等于 === 等值等型 != 不相等 !=== 不等值或不等型 > 大于 < 小于 >= 大于或等于 <= 小于或等于 ? 三元运算符 逻辑运算符
运算符 描述 && 与 ||
或 ! 非 类型运算符
运算符 描述 typeof 返回变量的类型 instanceof 返回 true,如果对象是对象类型的实例
# 数学Math
方法 | 描述 | 方法 | 描述 |
---|---|---|---|
round() | 四舍五入 | abs() | 绝对(正)值 |
ceil() | x 上舍入的整数 | floor() | x 下舍入的整数 |
pow() | x 的 y 次幂 | sqrt() | x 的平方根 |
sin() | 返回角的正弦 | cos() | 返回角的余弦 |
min() | 列表中最小值 | max() | 列表中最大值 |
random() | 0(包括)和1(不包括)之间的随机数 | abs() | 绝对(正)值 |
JavaScript提供了Math对象访问的 8 个数学常量
Math.E // 返回欧拉指数(Euler's number)
Math.PI // 返回圆周率(PI)
Math.SQRT2 // 返回 2 的平方根
Math.SQRT1_2 // 返回 1/2 的平方根
Math.LN2 // 返回 2 的自然对数
Math.LN10 // 返回 10 的自然对数
Math.LOG2E // 返回以 2 为底的 e 的对数(约等于 1.414)
Math.LOG10E // 返回以 10 为底的 e 的对数(约等于 0.434)
2
3
4
5
6
7
8
# 条件
if(条件){}
根据不同条件执行不同动作switch(){}
根据不同条件执行不同动作switch(表达式) { case n: 代码块 break; case n: 代码块 break; default: 默认代码块 }
1
2
3
4
5
6
7
8
9
10
# 循环
for(){}
遍历循环数组for(x in obj){}
遍历数组、对象、字符串forEach()
While(条件){}
会一直循环代码块,只要指定的条件为 trueDo/While
在检查条件是否为真之前,先执行一次代码,只要条件为真就会重复循环。
break、return、continue区别
- break:是立即结束当前语句,跳出循环体(只能向外跳出一层),后面的循环不会执行
- continue:跳出本次内层循环,重新开始下一次循环
- return:停止当前函数执行
- 停止当前函数执行
- 返回控制与函数结果
# this
JavaScript
this
关键词指的是它所属的对象
- 在方法中,this 指的是所有者对象
- 单独的情况下,this 指的是全局对象
- 在函数中,this 指的是全局对象
- 在函数中,严格模式下,this 是 undefined
- 在事件中,this 指的是接收事件的元素
箭头函数
若使用了箭头函数,那么this
表示定义箭头函数的对象,而不是调用该函数的元素/对象。
# 类
ECMAScript 2015,也称
ES6
,引入了 JavaScript 类。 JavaScript 类是 JavaScript 对象的模板。
- 访问器方法
Getters
是一个返回一个值的方法- 有返回语句
- 关键词
get
- 不需要参数
Setters
用于修改类中的属性- 关键词
set
- 有一个参数
- 关键词
- 语法
class CardId {
constructor(name,age,gender){
this.name = name;
this.age = age;
this.gender = gender;
}
isAge(){
if(this.age < 18){
return '未到18岁';
}
}
get cardName(){
return this.name;
}
set setNameValue(value){
this.name = value;
}
}
let card = new CardId('张三',27,'男');
// 使用getter与settter的调用
card.isAge card.setNameValue('李四');
// 普通方法的调用
card.isAge() card.setNameValue('李四');
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# JSON
JSON 是存储和传输数据的格式。(
J
avaS
criptO
bjectN
otation),简单来说,json本质就是字符串
let jsona = '{"gameList" :[{"title": "王者荣耀","type": "竞技"},{"title": "连连看","type": "休闲"}]}'
let jsonb = '[{"title": "王者荣耀","type": "竞技"},{"title": "连连看","type": "休闲"}]'
let jsonc = '{"title": "王者荣耀","type": "竞技"}'
// Json转Js对象
JSON.parse()
// Js转Json对象
JSON.stringify()
2
3
4
5
6
7
8
# 对象
对象存放有关联的数据,对象是无序的,通过属性名可以获取对象属性
- 创建对象
- 字面量创建(推荐)
- 关键词new创建
var obj = {
name:"张三",
age:20,
gender:'男'
};
var obj1 = new Object();
obj1.name = '李四'
2
3
4
5
6
7
获取对象属性及方法
- objectName.property
- objectName["property"]
- objectName.methodName()
管理对象
方法 | 描述 |
---|---|
Object.values(object) | 将对象变化为数组 |
Object.keys(object) | 以数组返回可枚举属性 |
Object.create() | 以现有对象为原型创建对象 |
Object.defineProperty(object, property, descriptor) | 添加或更改对象属性 |
Object.defineProperties(object, descriptors) | 添加或更改对象属性 |
Object.getOwnPropertyDescriptor(object, property) | 访问属性 |
Object.getOwnPropertyNames(object) | 以数组返回所有属性 |
Object.getPrototypeOf(object) | 访问原型 |
- 保护对象
方法 | 描述 |
---|---|
Object.preventExtensions(object) | 防止向对象添加属性 |
Object.isExtensible(object) | 如果属性可以添加到对象,则返回 true |
Object.seal(object) | 防止更改对象属性(不是值) |
Object.isSealed(object) | 如果对象被密封,则返回 true |
Object.freeze(object) | 防止对对象进行任何更改 |
Object.isFrozen(object) | 如果对象被冻结,则返回 true |
- 对象访问器(Getter 和 Setter)
与类中的Getter 和 Setter一样
- 优点
- 它提供了更简洁的语法
- 它允许属性和方法的语法相同
- 它可以确保更好的数据质量
- 有利于后台工作
# 对象构造器
用于创建相同“类型”的多个对象
原型继承
所有 JavaScript 对象都从原型继承属性和方法。
日期对象继承自 Date.prototype。数组对象继承自 Array.prototype。Person 对象继承自 Person.prototype。 Object.prototype 位于原型继承链的顶端。日期对象、数组对象和 Person 对象都继承自 Object.prototype。
function Person(name, age) {
this.name = name;
this.age = age;
}
// 通过prototype为对象构造器添加属性
Person.prototype.gender = "男";
// 也可以是方法
Person.prototype.name = function() {
return "姓名:" + this.name;
};
// 通过 new 关键词调用构造器函数可以创建相同类型的对象
var a = new Person('张三',20)
// 获取prototype为对象构造器添加的方法和属性
a.name() a.gender
2
3
4
5
6
7
8
9
10
11
12
13
14
# Map对象
Map对象用来保存键值对
方法 | 描述 | 方法 | 描述 |
---|---|---|---|
new Map() | 创建 Map 对象 | set() | 为 Map 对象的键设置值 |
get() | 获取 Map 对象中键的值 | entries() | 返回 Map 对象中键/值对的数组 |
keys() | 返回 Map 对象中键的数组 | values() | 返回 Map 对象中值的数组 |
clear() | 删除由键指定的元素 | delete() | 删除由键指定的元素 |
has() | 如果键存在,则返回 true | forEach() | 为每个键/值对调用回调 |
size | 获取 Map 中键的值 |
# Set 对象
Set 是唯一值的集合
方法 | 描述 | 方法 | 描述 |
---|---|---|---|
new Set() | 建新的 Set 对象 | add() | 向 Set 添加新元 |
clear() | 从 Set 中删除所有元素 | delete() | 删除由其值指定的元素 |
entries() | 返回 Set 对象中值的数组 | has() | 如果值存在则返回 tru |
forEach() | 为每个元素调用回调 | keys() | 返回 Set 对象中值的数组 |
values() | 与 keys() 相同 | size | 返回元素计数 |
# 函数
- 创建方式
- 函数声明
- 函数表达式(匿名函数) 创建的函数不会被提升
- Function() 构造器
- 箭头函数 创建的函数不会被提升
- 自调用函数
// 函数声明
function son(){}
// 函数表达式
var son = function(){}
// Function() 构造器
var son = new Function()
// 箭头函数
var son = () => {}
// 自调用函数
(function(){})()
(function(){}())
2
3
4
5
6
7
8
9
10
11
- 参数
// 形参
function son(a,b,c){
arguments //所有实参的集合,伪数组格式,可以循环遍历
caller //函数的调用
length //形参的个数
name //函数的名称
}
// 实参
son(1,2,3)
// 如果实参的个数不确定,形参直接不写
2
3
4
5
6
7
8
9
10
# 回调函数
- 回调函数
当一个函数作为参数传入另一个函数中,并且它不会立即执行,只有当满足一定条件后该函数才可以执行,这种函数就称为
回调函数
。// callback()就是回调函数 function getlist(id,callback){ if(id > 10){ callback(id) } } getlist(9,res=>{ console.log(res); })
1
2
3
4
5
6
7
8
9 - 同步任务
同步任务在主线程上排队执行,只有前一个任务执行完毕,才能执行下一个任务,JavaScript代码实际上是单线程的程序,那就决定了我们的代码是一行一行的顺序执行的,处理一些简短、快速的运算操作时主线程就够了,如果在同步程序中发送了网络请求,如果超时了,下面的代码依赖于网络请求,那么整个网页将会失去响应。
- 异步任务
异步任务不进入主线程,而是进入异步队列,前一个任务是否执行完毕不影响下一个任务的执行。一个异步过程的执行将不再与原有的序列有顺序关系,特别是对发送网络请求,不确保响应时间时候,异步是最优选择,网络请求无论多长时间,程序将不会在此等待,直接走下面的代码,等异步的请求有了响应,主线程几乎不用关心异步任务的状态了,自己完成回调后续的操作,程序间互不影响。
回调地狱
简单来说就是 回调函数里面嵌套回调函数,是实现代码
顺序执行
的一种操作方式,用于解决异步执行
缺点
- 代码可读性差,不利于维护
- 代码的扩展性差
- 多个回调之间难以建立联系
- 无法正常使用return 和throw
- 无法正常检索堆栈信息
解决回调地狱
- 回调函数
function getComment(id,callback){ uni.request({ url:"xxx", data:{aid:id}, success(res) { callback(res); } }) }, getComment(10,res=>{})
1
2
3
4
5
6
7
8
9
10
如果需要多个方法,依然出现多个嵌套,可读性差
# Promise
Promise
是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6
将其写进了语言标准,统一了用法,原生提供了Promise对象。
Promise有3种状态
- pending[待定] 初始状态
- resloved[实现] 操作成功
- rejected[被否决] 操作失败
用法
- 构造函数有两个参数:resloved和rejected,都是回调函数
- resloved函数:异步操作成功后调用,并将异步操作的结果传递出去
- rejected函数:异步操作失败后调用,将失败的信息传递出去
- .then():接收resloved函数传递过来的信息
- .catch():接收rejected函数传递过来的信息
Promise 状态发生改变,就会触发.then()里的响应函数处理后续步骤
Promise 状态一经改变,不会再变
Promise 实例一经创建,执行器立即执行
getComment(){
return new Promise((resolve,reject)=>{})
}
getComment()
.then(res=>{})
.catch(err=>{})
// 处理异步同步化
Promise.all([p1,p2,p3]).then(res=>{console.log(res)})
// Promise对象创建的调用
let p = new Promise((resolve,reject)=>{})
p.then(res=>{}).catch(err=>{})
2
3
4
5
6
7
8
9
10
11
12
# await / async
await / async 是ES7的新规范,异步处理同步化
- 为什么有async/await
- Promise虽然跳出了异步嵌套的怪圈,用链式表达更加清晰,但是我们也发现如果有大量的异步请求的时候,流程复杂的情况下,会发现充满了屏幕的then,看起来非常吃力,而ES7的async/await的出现就是为了解决这种复杂的情况
- async/await基本规则
- await关键字只能在使用async定义的函数中使用
- await后面可以直接跟一个Promise实例对象(可以跟任何表达式,更多的是跟一个返回Promise对象的表达式)
- await函数不能单独使用
- await可以直接拿到Promise中resolve中的数据
# promise和async/await区别
promise
是ES6,async/await
是ES7- async/await相对于promise来讲,写法更加优雅
- reject状态:
- promise错误可以通过catch来捕捉,建议尾部捕获错误
- async/await既可以用.then又可以用try-catch捕捉
# 闭包
声明在一个函数中的函数,叫做闭包函数。闭包指的是有权访问父作用域的函数,即使在父函数关闭之后。
function fun() {
let i = 0;
function a() {
i++;
console.log(`调用了${i}次`);
}
a()
}
2
3
4
5
6
7
8
- 优点
- 实现数据的私有
- 缺点
- 容易引起内存泄漏