一、基础
1、数据类型
- 值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、独一无二的值(Symbol)
- 引用数据类型:对象(Object)、数组(Array)、函数(Function)
JavaScript 变量生命周期在它声明时初始化,局部变量在函数执行完毕后销毁,全局变量在页面关闭后销毁。函数参数只在函数内起作用,是局部变量。
2、类型转换
| 方法 | 作用 |
|---|---|
| Number() | 转换为数字 |
| String()、 toString() | 转换为字符串 |
| Boolean() | 转换为布尔值 |
| toFixed() | 把数字转换为字符串,小数点后有指定位数的数字 |
| parseFloat() | 解析一个字符串,并返回一个浮点数 |
| parseInt() | 解析一个字符串,并返回一个整数 |
Number("99 88") // 返回 NaN
var y = "5"; // y 是一个字符串
var x = + y; // x 是一个数字
var y = "John"; // y 是一个字符串
var x = + y; // x 是一个数字 (NaN)
3、typeof——检测变量的数据类型
typeof "John" // string
typeof 3.14 // number
typeof false // boolean
typeof [1,2,3,4] // object
typeof {name:'John', age:34} // object
typeof new Date() // 返回 object
typeof function () {} // 返回 function
typeof myCar // 返回 undefined (如果 myCar 没有声明)
typeof null // 表示一个空对象引用,object
typeof undefined // undefined
typeof NaN // 返回 number
constructor 属性:返回所有 JavaScript 变量的构造函数
"John".constructor // 返回函数 String() { [native code] }
(3.14).constructor // 返回函数 Number() { [native code] }
false.constructor // 返回函数 Boolean() { [native code] }
[1,2,3,4].constructor // 返回函数 Array() { [native code] }
{name:'John', age:34}.constructor // 返回函数 Object() { [native code] }
new Date().constructor // 返回函数 Date() { [native code] }
function () {}.constructor // 返回函数 Function(){ [native code] }
可以使用 constructor 属性来查看对象是否为数组
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
4、作用域
作用域为可访问变量,对象,函数的集合。
- 局部作用域:变量在函数内声明,只能在函数内部访问。局部变量在函数开始执行时创建,函数执行完后局部变量会自动销毁。
- 全局作用域:变量在函数外定义,即为全局变量,网页中所有脚本和函数均可使用。全局变量是 window 对象。 如果变量在函数内没有声明(没有使用 var 关键字),该变量为全局变量。
// 此处可调用 carName 变量
function myFunction() {
carName = "Volvo";// 全局变量,可使用 window.carName访问
// 此处可调用 carName 变量
}
5、声明提升
函数及变量的声明都将被提升到函数的最顶部,变量可以在使用后声明,也就是变量可以先使用再声明。
x = 5; // 变量 x 设置为 5
var x; // 声明 x
只有声明的变量会提升,初始化的不会。
console.log(y) // undefined
var y = 7 // 初始化 y(变量声明 (var y) 提升了,但是初始化(y = 7) 并不会提升)
在严格模式(use strict)下你不能使用未声明的变量,会报错;同时,严格模式下不允许删除变量、对象、函数;不允许变量重名;不允许使用八进制;不允许使用转义字符;不允许对只读属性赋值等等。
6、 let 和 const(块级作用域)
ES2015(ES6) 新增加了let 和 const,let 声明的变量只在 let 命令所在的代码块内有效。const 声明一个只读的常量,声明时必须进行初始化,且初始化后值不可再修改。
块级作用域:let 和 const实现块级作用域,只在 所在的代码块 {} 内有效,在 {} 之外不能访问。
var x = 10;// 这里输出 x 为 10
{
let x = 2;// 这里输出 x 为 2
}
// 这里输出 x 为 10
循环作用域:var 声明的变量是全局的,包括循环体内与循环体外;let声明的变量作用域只在循环体内,循环体外的变量不受影响。
var i = 5;
for (var i = 0; i < 10; i++) {}
// 这里输出 i 为 10
let i = 5;
for (var i = 0; i < 10; i++) {}
// 这里输出 i 为 5
window 对象:var 关键字声明的全局作用域变量属于 window 对象;let 声明的全局作用域变量不属于 window 对象。
const 的本质: const 定义的变量并非常量不可变,它定义了一个常量引用一个值。使用 const 定义的对象或者数组,其实是可变的。
const car = {type:"Fiat", model:"500", color:"white"};// // 创建常量对象
car.color = "red";// 修改属性
car = {type:"Volvo", model:"EX60", color:"red"}; // 错误
const cars = ["Saab", "Volvo", "BMW"];// 创建常量数组
cars[0] = "Toyota";// 修改元素
cars.push("Audi");// 添加元素
cars = ["Toyota", "Volvo", "Audi"]; // 错误
不能使用 let 关键字来重置 var 关键字声明的变量,不能使用 var 关键字来重置 let 关键字声明的变量。let、const 声明的变量不能声明提升;
二、正则表达式
正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串搜索模式。
// 语法
/正则表达式主体/修饰符(可选)
var patt = /runoob/i // runoob 是一个正则表达式主体 (用于检索),i 是一个修饰符 (搜索不区分大小写)
| 修饰符 | 描述 |
|---|---|
| i | 对大小写不敏感 |
| g | 全局匹配(查找所有匹配而非在找到第一个匹配后停止) |
| m | 多行匹配 |
| 表达式 | 描述 |
|---|---|
| [abc] | 查找方括号之间的任何字符 |
| [0-9] | 查找任何从 0 至 9 的数字 |
| (x竖线y) | 查找任何以竖线分隔的选项 |
| 量词 | 描述 |
|---|---|
| n+ | 匹配任何包含至少一个 n 的字符串 |
| n* | 匹配任何包含零个或多个 n 的字符串 |
| n? | 匹配任何包含零个或一个 n 的字符串 |
| 元字符 | 描述 |
|---|---|
| \d | 查找数字 |
| \s | 查找空白字符 |
| \b | 匹配单词边界 |
| \uxxxx | 查找以十六进制数 xxxx 规定的 Unicode 字符 |
- search():检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,并返回子串的起始位置
var str = "Visit Runoob!";
var n = str.search(/Runoob/i); // 6
- replace():在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串
var txt = str.replace(/microsoft/i,"Runoob");
- test():检测一个字符串是否匹配某个模式,如果字符串中含有匹配的文本,则返回 true,否则返回 false
/e/.test("The best things in life are free!")
- exec(): 用于检索字符串中的正则表达式的匹配。该函数返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为 null
/e/.exec("The best things in life are free!");
三、this 关键字
this 表示当前对象的一个引用。在 JavaScript 中 this 不是固定不变的,它会随着执行环境的改变而改变。
| 执行环境 | 对象 |
|---|---|
| 方法 | 该方法所属的对象 |
| 单独使用 | 全局对象 |
| 函数 | 全局对象,在严格模式下,this 是未定义的(undefined) |
| 事件 | 接收事件的元素 |
| call()、apply() | 将 this 引用到任何对象 |
显式函数绑定
call()、apply()允许切换函数执行的上下文环境(context),即 this 绑定的对象。
var person1 = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
var person2 = {
firstName:"John",
lastName: "Doe",
}
person1.fullName.call(person2); // 返回 "John Doe"
四、异步
- 同步:同步不意味着所有步骤同时运行,而是指步骤在一个控制流序列中按顺序执行;
- 异步:不保证同步,执行将不再与原有的序列有顺序关系。异步就是从主线程发射一个子线程来完成任务。
- 异步使用场景:
用子线程来完成消耗时间足够长以至于被用户察觉的事情,比如读取一个大文件或者发出一个网络请求。子线程独立于主线程,即使出现阻塞也不会影响主线程的运行。但是子线程一旦发射了就会与主线程失去同步而无法确定是否结束,如果结束之后需要处理一些事情,比如处理来自服务器的信息,我们是无法将它合并到主线程中去的。
为了解决这个问题,JavaScript 中的异步操作函数往往通过回调函数来实现异步任务的结果处理。
- 回调函数:
在启动一个异步任务的时候就告诉它:等你完成了这个任务之后要干什么。这样一来主线程几乎不用关心异步任务的状态了,他自己会善始善终。
function print() {
document.getElementById("demo").innerHTML="RUNOOB!";
}
setTimeout(print, 3000);// print就是一个回调函数
五、Promise
Promise 是一个 ECMAScript 6 提供的类,目的是更加优雅地书写复杂的异步任务。
Promise 构造函数只有一个函数参数,这个函数在构造之后会直接被异步运行,所以我们称之为起始函数。起始函数包含两个参数 resolve 和 reject。resolve 和 reject 都是函数,其中调用 resolve 代表一切正常,reject 是出现异常时所调用的。
Promise 类有 .then() .catch() 和 .finally() 三个方法,参数都是函数,.then() 可以将参数中的函数添加到当前 Promise 的正常执行序列,.catch() 则是设定 Promise 的异常处理序列,.finally() 是在 Promise 执行的最后一定会执行的序列。
new Promise(function (resolve, reject) {
var a = 0;
var b = 1;
if (b == 0) reject("Divide zero");
else resolve(a / b);
}).then(function (value) {
console.log("a / b = " + value);// a / b = 0
}).catch(function (err) {
console.log(err);
}).finally(function () {
console.log("End");// End
});
resolve()、return用于向下一个 then 传递一个值。但是,如果 then 中返回的是一个 Promise 对象,那么下一个 then 将相当于对这个返回的 Promise 进行操作。
- resolve 和 reject 的作用域只有起始函数,不包括 then 以及其他序列;
- resolve 和 reject 并不能够使起始函数停止运行,别忘了 return。
new Promise(function (resolve, reject) {
console.log(1111);//1111
resolve(2222);
}).then(function (value) {
console.log(value);//2222
return 3333;
}).then(function (value) {
console.log(value);//3333
throw "An error";
}).catch(function (err) {
console.log(err);//An error
});
六、异步函数
异步函数(async function)是 ECMAScript 2017 标准的规范,await 指令后必须跟着一个 Promise,异步函数会在这个 Promise 运行中暂停,直到其运行结束再继续运行。
async function asyncFunc() {
await print(1000, "First");
await print(4000, "Second");
await print(3000, "Third");
}
asyncFunc();
异步函数实际上原理与 Promise 原生 API 的机制是一模一样的,处理异常的机制将用 try-catch 块实现:
async function asyncFunc() {
try {
await new Promise(function (resolve, reject) {
throw "Some error"; // 或者 reject("Some error")
});
} catch (err) {
console.log(err);
// 会输出 Some error
}
}
asyncFunc();