# 变量
声明:使用关键词生成局部变量/不使用关键词生成全局变量。
运算:undefined在boolean中为false,在number中则为NaN,对应的null则会转为0,boolean中同样为false。
变量提升:
- var:允许先使用变量后声明变量,但使用时变量的值为undefined
- const/let:同样会被提升到代码块的顶部但是不会赋予初始值,使用时会抛出错误(ReferenceError)。这个变量从代码块一开始时处于一个“暂时性死区”,直到这个变量被声明为止。
- 函数:函数声明(直接用function定义函数)会被提升到顶部,但函数表达式(var baz = function(){})无法被提升,哪怕是用var定义。
# 数据类型与结构
基本数据类型: boolean、null、undefined、number、bigInt、string、symbol、object
数据类型的转换:
- 数字转字符串:+运算符即可,注意-运算符时会将string转为number。
- 字符串转数字:一元加法运算符
(+"1.1") + (+"1.1") = 2.2;
// 加入括号是为了清楚展示,并非必需的
# 字面量
字面量是脚本中按字面意思给出的固定的值,而不是变量。 注意:
- 在es6中,对象字面值扩展了:支持在创建时设置原型、简化了属性值与属性名相同时的写法、方法定义、支持父方法调用以及动态计算属性名
let obj = {
// __proto__ 设置原型
__proto__: theProtoObj,
// Shorthand for ‘handler: handler’
handler,
// Methods
toString() {
// Super calls
return "d " + super.toString();
},
// Computed (dynamic) property names 动态属性名
["prop_" + (() => 42)()]: 42,
};
2.在字符串字面值上使用字符串对象的所有方法,js会自动将字符串字面值转换一个临时的字符串对象,调用该方法,然后废弃到临时的字符串对象。在字符串中使用的特殊字符
字符 | 意思 |
---|---|
\0 | Null字节 |
\b | 退格符 |
\f | 换页符 |
\n | 换行符 |
\r | 回车符 |
\t | Tab |
\v | 垂直Tab |
' | 单引号 |
'' | 双引号 |
\ | \ |
# 异常处理语句
- throw语句 使用throw语句抛出一个异常,当你抛出异常,一个含有值的表达式要被抛出
throw "Error2"; // String type
throw 42; // Number type
throw true; // Boolean type
throw {
toString: function () {
return "I'm an object!";
},
};
// 抛出异常时声明一个对象,catch中可以查询到对象属性
// Create an object type UserException
function UserException(message) {
this.message = message;
this.name = "UserException";
}
// Make the exception convert to a pretty string when used as
// a string (e.g. by the error console)
UserException.prototype.toString = function () {
return this.name + ': "' + this.message + '"';
};
// Create an instance of the object type and throw it
throw new UserException("Value too high");
- try...catch 一个或多个try+0个或1个catch try中语句块若抛异常,立即进入catch语句块 try中语句块无异常,则跳过catch语句块 finally语句块在try...catch后执行,finally返回的值,将是整个try-catch-finally流程返回值,不管try...catch发生了什么
- 使用Error对象 根据错误类型,可以使用'name'和'message'获取信息,name提供了常规的错误类,而message提供了一条错误对象转字符串的简明信息。抛出个人异常的时候,应该使用Error构造函数
throw (new Error('出错了'))
# 循环
# 循环的几种方式
- for
- do...while
- while
- for...in
- for...of
# label语句
添加label可以跳出整个循环,如
outPoint: for (var i = 0; i < 10; i++) {
for (var j = 0; j < 10; j++) {
if (i == 5 && j == 5) {
break outPoint; // 在 i = 5,j = 5 时,跳出所有循环,
// 返回到整个 outPoint 下方,继续执行
}
num++;
}
}
// 此时num是55;跳出outPoint标识的循环,如果是continue,则是跳出本次循环,并跳转到标签后的循环内
# for...in与for...of的区别
- for...in:循环一个指定变量来循环一个对象的所有可枚举属性
- for...of:在可迭代对象上创建一个循环,对值的每一个独特属性调用一个迭代。
for...in循环数组的结果是元素的下标,而for...of是元素的值
# 函数
# 定义函数
- 函数声明:function关键词+函数名
- 函数表达式:
// 匿名函数
const func = function(){}
// 非匿名函数,为function提供名称,可以通过该名字调用。
const func = function fac(n){
n++;
return n>2?2:fac(n);
}
- Function对象构造函数:直接调用此构造函数可以动态创建函数,但构造函数创建的函数只能在全局作用域中运行。因此不会创建当前环境的闭包,因为它们总是被创建于全局环境。也就不能访问它们被构造函数创建时所在的作用域变量。
- 自定义构造函数:通过new关键词,首先创造出一个新的对象,然后将该对象的上下文作为构造函数的this。最后再将得到的对象返给变量
function getNewStudent(){
this.name =function(){
return this
}
return 1
}
const student = new getNewStudent(); //{ name:function(){return this}}
const student1 = getNewStudent() //1
注意:当构造函数的返回值是一个对象时,对传入的this设置的任何操作都无效,最终new 返回的就是这个指定对象而不是额外构造的对象。仅当值的类型不为对象时,构造函数将无视返回值,返回一个构造完毕的对象。
# 调用函数
函数根据调用方式分为三种
- 立即执行函数
- 方法
- 构造函数
不同类型函数调用之间的区别主要在于:隐式传入的this指向不同,方法中的函数传入对象,立即执行函数传入window,构造函数传入对象实力。而apply和call可以显示地传递this指向。唯一的区别就是apply的传参是数组形式,call是列表形式。第一个参数是this指向,剩余参数就是函数的传参。
juggle.apply(ninja,[1,2,3,4]);
juggle.call(ninja,1,2,3,4);`
# 闭包与作用域链
在一个函数内嵌套一个函数,嵌套函数对于容器函数来说是私有的,而嵌套函数自身也形成了一个闭包。
闭包的概念:封闭了表达式,闭包可以拥有独立变量以及绑定了这些变量的环境的表达式。嵌套函数可以“继承”容器函数的参数和变量,也就是包含了容器函数的作用域。容器函数却不能使用它的参数和变量。
作用域链:多层嵌套函数的关系中,如a中嵌套了b,b中嵌套了c,那么c的闭包包含了b的函数作用域,但是由于b的闭包包含了a的函数作用域,因此它们递归的包含了所有包含它的作用域,这就是作用域链。
在作用域链中,链的第一个元素就是最里面的作用域,最后一个是最外层的,所以当变量命名冲突时,更近的作用域拥有更高的优先级。
当然,由于这种优先级的存在,一旦出现冲突,内部函数将无法访问外部函数的这个变量,因为已经被内部函数的同名变量覆盖了。
# arguments对象
arguments对象保存函数的实参数,它是一个类数组,它可以使用索引访问数组,也可以使用数组的length属性,但是不具备其他Array对象的数组操作方法,所以称为类数组。
# 函数参数
- 默认参数:参数设置默认值,不设置即为undefined
function multiply(a, b = 1) {
return a * b;
}
- 剩余参数:使用...收集剩余的参数进一个数组。
function multiply(multiplier, ...theArgs) {
return theArgs.map((x) => multiplier * x);
}
const arr = multiply(2, 1, 2, 3);
# 表达式与运算符
# 逻辑运算符
运算符 | 范例 | 说明 |
---|---|---|
逻辑与&& | a&&b | a为true时,返回b |
逻辑或|| | a||b | a为false时,返回b |
逻辑非! | !a | 返回true/false |
注:短路求值的时候第二个表达式不会执行(如true||表达式)
# 一元操作符
- delete 删除一个对象的属性或者数组中的一个值。如果操作成功,返回true。删除数组中的元素时,只是将该索引的值变为了undefined,数组长度不变。
delete objectName.property;
delete objectName[index];
- typeof 返回一个表示类型的字符串
// 返回string和boolean,字符串和布尔值,包括String()和Boolean()
typeof true; // returns "boolean"
typeof "Hello world"; // returns "string"
typeof String(1) // returns 'string'
// 返回number和bigint
typeof 62; // returns "number"
typeof 42n // returns 'bigint'
typeof NaN // returns 'number' NaN返回数字类型
// 返回symbol,包括Symbol()
typeof Symbol('foo') // returns 'symbol'
// 返回undefined,包括不存在的变量或属性
typeof undefined // 'undefined'
typeof ttttttt // 'undefined'
// 返回function,包括es6的class、各个内置对象本身除了Math,以及Function(),new Function()
typeof class cs {} // returns 'function'
typeof parseInt; // returns "function"
typeof Date; // returns "function" 内置对象返回function类型
typeof Function; // returns "function"
typeof Option; // returns "function"
typeof String; // returns "function"
// 返回object,对象、数组、null、正则表达式,还有Math和JSON本身,还有使用new操作符的数据,除了Function以外
typeof null; // returns "object" null返回为对象类型
typeof Math; // returns "object"
typeof /d/ // returns 'object'
注意: 1、在let和const之前无法typeof,会报错 2、typeof null的解释: 在JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于null代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0,typeof null 也因此返回 "object"。 3、typeof无法精确判断出null、数组、对象、正则的类型,若想精准判断类型,需要使用Object.prototype.toString.call 4、BigInt类型 BigInt 来自于 ES11 增加的一种最新的基础类型,可以用任意精度表示整数。 它提供了一种表示大于 2^53 - 1 整数的方法,能表示任意大的整数。 它是通过在整数末尾附加 n 或调用构造函数 BigInt() 来创建的。 IE 不支持。 无法与number进行混合运算,会报类型错误
- void 表示一个运算没有返回值
# 关系运算符
- in 指定属性存在于指定对象中,则返回true
var mycar = { make: "Honda", model: "Accord", year: 1998 };
"make" in mycar; // returns true
- instanceof 如果所判别的对象确实是所指定的类型,则返回true
objectName instanceof objectType;
# 正则表达式
# 创建正则表达式
var re = /ab+c/;
var re = new RegExp("ab+c");
两种方式的不同之处就是,用构造函数创建的正则表达式会被编译,如果是动态生成的或者将被改变的就需要用构造函数来创建。
# 特殊字符
- 断言:表示一个匹配在某些条件下发生。
- 字符类:区分不同类型的字符,如字母和数字。
- 组和范围:表示表达式字符的分组和范围。
- 量词:表示匹配的字符或表达式的数量
- Unicode属性转义:基于Unicode字符属性区分字符。例如大小写字母和数字符号标点等等。
字符 | 含义 |
---|---|
\ | 转义符,注意传给构造函数的特殊字符要额外加一个转义符 |
^ | 匹配输入的开始,如/^A/ 不会匹配"anA"中的A,但会匹配"Ana"中的A |
$ | 匹配输入的结束,同上 |
* | 匹配前一个表达式0次或多次,等价于{0,} |
+ | 匹配前一个表达式1次或多次,等价于{1,} |
? | 匹配前一个表达式0次或1次,等价于{0,1}。如果紧跟在任何量词(*,+,?,{})后面,将会使量词变为非贪婪(匹配尽量少的字符),缺省时则是贪婪模式。例如对“123abc”使用/\d+/将会匹配123,但是/\d+?/则只有1 |
. | 默认匹配除换行符之外的任何单个字符,如/.n/ |
(x) | 匹配x并记住匹配项 ,\1,\2表示第一个和第二个被捕获括号匹配的子字符串 |
(?:x) | 匹配x但是不记住匹配项,非捕获括号,可以当成子表达式用 |
x(?=y) | 匹配x但仅匹配紧跟y的x,先行断言 |
(?<=y)x | 匹配x但仅匹配前置是y的x,后行断言 |
x(?!y) | 匹配x但仅匹配不跟着y的x,正向否定查找 |
(<!y)x | 匹配x但仅匹配前置不是y的x,反向否定查找 |
x | y |
{n} | 匹配前面一个字符刚好出现了几次 |
{n,} | 匹配前面一个字符至少出现了几次 |
{n,m} | 匹配前面一个字符至少出现n次,至多出现m次 |
[xyz] | 一个字符集合,匹配方括号内的任意字符,可以用-来指定范围 |
[^xyz] | 一个反向字符集合,匹配没有在方括号内的任意字符,可以用-来指定范围 |
[\b] | 匹配一个退格 |
\b | 匹配一个词的边界,开头或者结尾,比如放后面就是以xx结尾,放前面就是以xx开头 |
\B | 匹配一个非单词边界,字符串第一个或者最后一个字符为非‘字’字符 |
\cX | 当X是处于A到Z之间的字符的时候,匹配字符串中的一个控制符 |
\d | 匹配一个数字,等价于[0-9] |
\D | 匹配一个非数字字符,等价于[^0-9] |
\f | 匹配一个换页符 |
\n | 匹配一个换行符 |
\r | 匹配一个回车符 |
\s | 匹配一个空白字符,包括空格、制表符、换页符、换行符 |
\S | 匹配一个非空白字符 |
\t | 匹配一个水平制表符 |
\v | 匹配一个垂直制表符 |
\w | 匹配一个单字字符,相当于[A-Za-z0-9] |
\W | 匹配一个非单字字符 |
\n | 第n个子捕获匹配的字符串 |
\0 | 匹配null字符串 |
# 使用插入语
任何正则表达式的插入语都会使这部分匹配的副字符串被记忆。一旦被记忆,这个副字符串就可以被调用于其他用途。 比如/Chapter (\d+).\d*/用于匹配"Open Chapter 4.3, paragraph 6"时,'4'会被记住。 但是括号内用?:\d+则不会被记住