Skip to content

JavaScript基础

1 介绍

2 引入方式

js代码也是书写在html中的,那么html需要引入JS代码

方式有2种

第一种方式: 内部脚本,将JS代码定义在HTML页面中

  • JavaScript代码必须位于<script></script>标签之间
  • 在HTML文档中,可以在任意地方,放置任意数量的<script>
  • 一般会把脚本置于<body>元素的底部,可改善显示速度

例子:

html
<script>
    alert("Hello JavaScript")
</script>

第二种方式: 外部脚本将, JS代码定义在外部 JS文件中,然后引入到 HTML页面中

  • 外部JS文件中,只包含JS代码,不包含<script>标签
  • 引入外部js的<script>标签,必须是双标签

例子:

html
<script src="js/demo.js"></script>

注意:demo.js中只有js代码,没有<script>标签

3 语法-书写语法

掌握了js的引入方式,那么接下来我们需要学习js的书写了,首先需要掌握的是js的书写语法用Java编写规范即可

语法规则如下:

  • 区分大小写:与 Java 一样,变量名、函数名Java中的方法名以及其他一切东西都是区分大小写的
  • 每行结尾的分号;可有可无 Java中有,建议写
  • {}大括号表示代码块
  • 注释:和Java一样
    • 单行注释:// 注释内容
    • 多行注释:/\* 注释内容 \*/

借助js中3钟输出语句,来演示书写语法

api描述
window.alert()警告框
document.write()在HTML输出内容
console.log()写入浏览器控制台
html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JS-基本语法</title>
</head>
<body>
    
</body>
<script>
    /* alert("JS"); */

    //方式一: 弹出警告框
    // window.alert("hello js");

    // //方式二: 写入html页面中
    // document.write("hello js");

    //方式三: 控制台输出
    console.log("hello js");
</script>
</html>

4 语法-变量 🍐

学习js中变量的声明

  1. 在js中,变量的声明和java中还是不同
  2. js中主要通过如下3个关键字来声明变量的:
关键字解释
var早期ECMAScript5中用于变量声明的关键字
letECMAScript6中新增的用于变量声明的关键字,相比较var,let只在代码块内生效
const声明常量的,常量一旦声明,不能修改

在js中声明变量还需要注意如下几点:

  • JavaScript 是一门弱类型语言,变量可以存放不同类型的值 。
  • 变量名需要遵循如下规则按照Java规范即可:
    • 组成字符可以是任何字母、数字、下划线(_)或美元符号($
    • 数字不能开头
    • 建议使用驼峰命名
html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JS-基础语法</title>
</head>
<body>
    
</body>
<script>

    //var定义变量
    // var a = 10;
    // a = "张三";
    // alert(a);

    //特点1 : 作用域比较大, 全局变量
    //特点2 : 可以重复定义的
    // {
    //     var x = 1;
    //     var x = "A";
    // }
    // alert(x);

    //let : 局部变量 ; 不能重复定义 
    // {
    //     let x = 1;
    //     alert(x);
    // }
    
    //const: 常量 , 不能给改变的.
    const pi = 3.14;
    pi = 3.15;
    alert(pi);

</script>
</html>

注意事项

  1. 在js中,我们var声明的变量可以接受任何数据类型的值。并且var声明的变量的作用于是全局的,注释掉之前的代码,
javascript
    //var定义变量
    var a = 10;
    a = "张三";
    a=true;
    alert(a);
  1. 在ECMAScript 6 新增了 let 关键字来定义变量,它的用法类似于 var,但是所声明的变量,只在 let关键字所在的代码块内有效,且不允许重复声明,否则会出现错误

  2. 在ECMAScript6中简称:ES6,还新增了const 关键字用来声明常量,但是一旦声明,常量的值是无法更改的。注释之前的内容,否则会出现错误:

5 语法-数据类型和运算符 🍐

数据类型

虽然js是弱数据类型的语言,但是js中也存在数据类型,js中的数据类型分为 :原始类型 和 引用类型,具体有如下类型

数据类型描述
number数字(整数、小数、NaN(Not a Number))
string字符串,单双引皆可
boolean布尔true,false
null对象为空
undefined当声明的变量未初始化时,该变量的默认值是 undefined

使用typeof函数可以返回变量的数据类型,接下来我们需要通过书写代码来演示js中的数据类型

javascript
//原始数据类型
    alert(typeof 3); //number
    alert(typeof 3.14); //number

点击查看验证代码

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JS-数据类型</title>
</head>
<body>

</body>
<script>

    //数字类型
    alert(typeof 3); //number
    alert(typeof 3.14); //number

// 字符串类型
    alert(typeof "A"); //string
    alert(typeof 'Hello');//string
    //布尔类型
    alert(typeof true); //boolean
    alert(typeof false);//boolean

    //对象
    alert(typeof null); //object 

    //undefined未定义
    var a ;
    alert(typeof a); //undefined
    
</script>
</html>

运算符

js中的运算规则绝大多数还是和java中一致的和Java一样,具体运算符如下:

运算规则运算符
算术运算符+ , - , \* , / , % , ++ , --
赋值运算符= , += , -= , *= , /= , %=
比较运算符> , < , >= , <= , != , == , === 注意 == 会进行类型转换,=== 不会进行类型转换**java不一样
逻辑运算符&&
三元运算符条件表达式 ? true\_value: false\_value

注意

  1. 在js中,绝大多数的运算规则和java中是保持一致的三元运算符也有,但是js中的==和===是有区别的。
  • ==:只比较值是否相等,不区分数据类型,哪怕类型不一致,==也会自动转换类型进行值得比较
  • ===:不光比较值,还要比较类型,如果类型不一致,直接返回false
javascript
var age = 20;
var _age = "20";
alert(age == _age);//true ,只比较值
alert(age === _age);//false ,类型不一样
  1. 流程控制语句 if,switch,for等和java保持一致,此处不再演示

在js中,虽然不区分数据类型,但是有时候涉及到数值计算,还是需要进行类型转换的,js中可以通过parseInt()函数来进行将其他类型转换成数值类型。注释之前的代码,添加代码如下:

javascript
// 类型转换 - 其他类型转为数字
alert(parseInt("12")); //12
alert(parseInt("12A45")); //12
alert(parseInt("A45"));//NaN (not a number)
  1. 需要注意的是: 在js中,0,null,undefined,"",NaN理解成false,反之理解成true
javascript
var a=0;
//a =null; a=""  a=undefined
if(a){
    //不会执行
}

6 语法-函数 ✏️ 🍐

函数

  1. java中我们为了提高代码的复用性,可以使用方法
  2. 在JavaScript中可以使用函数来完成相同的事情
    • JavaScript中的函数被设计为执行特定任务的代码块 (封装),通过关键字function 来定义
    • JS中定义函数有2中方式

第一种定义格式如下常用:

javascript
function 函数名(参数1,参数2..){
    要执行的代码
}

因为JavaScript是弱数据类型的语言,所以有如下几点需要注意: 👈

  • 形式参数不需要声明类型,并且JavaScript中不管什么类型都是let或者var去声明,加上也没有意义。
  • 返回值也不需要声明类型,直接return即可

如下示例:

javascript
function add(a, b){
    return a + b;
}

接下来我们需要在Idea或者VS中编写代码来演示

第一步:新建名为js的文件夹,创建名为01. JS-函数的html文件,然后在<script>中定义上述示例的函数:

html
<script>
     function add(a,b){
        return  a + b;
     }
</script>

但是上述只是定义函数,**函数需要被调用才能执行!**所以接下来我们需要调用函数

第二步:因为定义的add函数有返回值,所以我们可以接受返回值,并且输出到浏览器上,添加如下代码:

javascript
let result = add(10,20);
alert(result);

第二种可以通过var去定义函数的名字,具体格式如下:

javascript
var functionName = function (参数1,参数2..){   
	//要执行的代码
}

接下来我们按照上述的格式,修改代码如下:只需要将第一种定义方式注释掉,替换成第二种定义方式即可,函数的调用不变

html
<script>

    //定义函数-1
    // function add(a,b){
    //    return  a + b;
    // }

    //定义函数-2
    var add = function(a,b){
        return  a + b;
    }


    //函数调用
    var result = add(10,20);
    alert(result);
    
</script>

注意

我们在调用add函数时,再添加2个参数,修改代码如下:

javascript
var result = add(10,20,30,40);

浏览器打开,发现没有错误,并且依然弹出30,这是为什么呢?

因为在JavaScript中,函数的调用只需要名称正确即可,参数列表不管的。如上述案例,10传递给了变量a,20传递给了变量b,而30和40没有变量接受,但是不影响函数的正常调用。

数据类型(8种) Type

JavaScript的8种原始数据类型包括Number、String、Boolean、Null、Undefined、Symbol(ES6新增)、BigInt(暂时不必关注),此外有Object类型。函数被认为是可执行的object类型变量,但typeof会返回'function'。

Number

不区分整数和浮点(内部区分),注意浮点计算结果是不精确的(由于浮点数的计算方式,如0.1+0.2=0.30000000000000004),对浮点数不建议直接用等号判断两值相等,应当看他们的差是否小于某个值(如0.001)。Infinity(超过Number最大值)、NaN(Not a Number)也是合法的Number。

关于NaN

NaN是特殊的Number,它也不等于自己,只能通过isNaN()判断。

String

单引号‘’或双引号""包裹的字符串。

Boolean

Boolean包括'true'、'false'两种取值。比较运算符、&&、||与!都可能产生布尔值。

转换结果为false的取值

NaN、null、undefined、0与空字符串转Boolean的结果都为false。

Null

null表示空值,undefined表示未赋值,undefined可以用于判断函数参数是否传递。他们是两种数据类型。

Undefined

访问对象未声明的属性、函数未接受到的参数、未初始化的变量都会返回undefined。

null和undefined的注意事项

  1. null是保留字,而undefined不是。

  2. 如果访问不存在的变量,会报错"var is not defined";访问已声明但未赋值的变量才会得到undefined。

  3. typeof null的结果是object,但null也是一种基本类型而非object,这个混淆是由于typeof以内存低位判断数据类型,object和null的低3位都是0。

ymbol ES6

用于产生唯一标识,除了自己等于自己,两个完全相同的symbol不相等,常用于对象属性、声明唯一常量、定义私有属性。也可以用Symbol.for()创建symbol,如果参数一致,创建的symbol相等。

js
let s = Symbol("")
let s1 = Symbol("")
s == s1//false
s === s//true
let s2 = Symbol.for("")
let s3 = Symbol.for("")
s2 == s3//true

你可以通过以下方式获取Symbol的description(无需记忆)。

js
let s2 = Symbol("love")
let obj = {[s2]:"and peace"}
obj//{ [Symbol(love)]: 'and peace' }
Object.getOwnPropertySymbols(obj)//[ Symbol(love) ]
Reflect.ownKeys(obj)//[ Symbol(love) ]

Symbol定义了对象的许多实用方法,包括[Symbol.Iterator]、[Symbol.match]、[Symbol.replace]、[Symbol.split]、[Symbol.toPrimitive]、[Symbol.toStringTag]等。toStringTag方法甚至能改变对象的toString方法。

*BigInt ES6

在数字末尾加n可声明BigInt,其可操作大于Number所能表示最大数的数(2^53)。该类型尚在提案过程中,在新版Chrome与Node中得到实现。

带小数的运算会被取整。

js
let Num = BigInt(Math.pow(2,63))
let Num2 = 100n

Object

键-值对的无序集合。键(key)只能是字符串类型,值(value)可以是任意类型。'.'可以用于表示键路径,比如obj.key或obj.obj.a。

Object是引用类型,存储的是指针,而其他基本类型存储值。

js
let obj = {key:'value',
           obj:{
             a:'a'
           }}

Array

用[]或new Array()创建,数组可以包含任意类型元素并且提供了相当多的方法。

Date

Date类型提供了丰富的与时间、日期相关的方法,Date()返回当前日期的字符串。

RegExp

正则表达式对象。

Map&Set ES6

ES6新增的数据结构。

Map是一组key-value对结构,key不能重复,否则只保留最新的值。与对象只支持string与symbol相比,Map 的key支持任意类型。

js
let students = new Map([['Lucy',90],['Peter',80],['Bill',85]])
students.get('Lucy')//90
students.has('Peter')//true
students.delete('Peter')//true
students.get('Peter')//undefined
students.set('Bill',90)//Map { 'Lucy' => 90, 'Bill' => 90 }
students.get('Bill')//90

Set类似集合,由一组不重复的key组成,否则只保留一个。

js
let foods = new Set(['Chicken','Noodles','Rice'])
foods.add('fish')//Set { 'Chicken', 'Noodles', 'Rice', 'fish' }
foods.delete('Noodles')//true
foods.has('Rice')//true

获取基本类型:typeof

typeof var可以获取变量类型,不与ES规范一一对应,其返回值是以下结果之一:

返回数据类型对应基础类型
numberNumber
stringString
booleanBoolean
objectObject Null
undefinedUndefined(该变量不存在)
symbolSymbol
functionObject
bigintBigInt

获取实例类型:instanceof

instanceof用于判断检测对象的类型,包括"Array"、"Function"、"Object"及自定义类/构造函数等。

此外Object.prototype.toString.call()可以准确打印出Null的类型。也可以通过访问".constructor"获取构造函数判断类型。

js
let a = []
typeof a//'object'
a instanceof Array//true

class y{}
let t = new y()
t instanceof y//true

动态类型&类型转换

作为动态语言,JS允许同一个变量在不同时间用作不同类型。

使用JavaScript函数转换

例如全局方法(构造函数)String()、Number()、Date()以及变量的toString()方法等。不同类型还会有独有的方法比如Date变量的getDate()、getDay(),Number变量的toPrecision()等。

使用JavaScript自动转换

变量类型会根据需要发生类型转换,例如:

js
5 + null //5 因为null=0
5 + undefined //NaN 因为undefined转为数字是NaN
"0"+ null //"0null" 因为null="null"
"5" + 1 //"51" 因为1="1"
1 + "5" //"51" 因为1="1"
"5" - 1 //4 因为"5"=5
[1,2] + 1//"1,21" 数组先转字符串,再加"1"
if("str"){
  //这里的代码将会执行,因为“str”可以转为true
}

可以观察到含字符串类型会转为字符串,没有或不能转字符串的话转数字(除加号以外,结果转数字)。

自动转换有一些基础规则,比如Boolean值的转换:true等于1,false等于0,空字符串、空数组和null等于0,非纯数字字符串转为NaN等。

有趣的是,"0"可以转为Boolean的“true”,但“0”转为数字0之后再转Boolean就会变成“false”。空数组也可以转“true”,转数字之后也为0。

基本类型&引用类型

JS通过引用操作对象,引用类型变量的复制不会引起对象复制(可以理解为复制指针),但基本类型变量的复制会在内存中产生两份变量。

let a={}; let b=a; a.x=0; //a===b

let c=5; let d=c; c=6; //c!==d

基本类型包装

除了Object类型存储的是引用,所有类型都是基本类型(存储值),但除了null和undefined,他们都像对象一样拥有自己的方法。这不是因为基本类型具有方法,而是在调用基本类型的方法时,JS引擎自动包装了基本类型,调用结束后销毁对象。

因此,向基本类型添加属性是无效的,因为添加完成后临时对象即被销毁,但可以向其原型添加属性和方法。

js
var str = 'str'
str.toUpperCase()
/*
相当于做了这些事
var _str = new String(str)
str = _str.toUpperCase()
*/

变量声明 Declaration

var

变量用var声明,不用var则作为全局变量。var声明的变量处于全局作用域或函数作用域。

变量提升 Hoisting

用var声明的变量,可以在声明语句之前使用,但不会初始化(赋值)。因此访问他们虽然不会报错,但会得到undefined。

let&const ES6

ES6中新增了let与const关键字,分别代表块级作用域中的变量与常量,同时不允许重复声明,没有变量提升。

TIP

const定义的对象并非常量,const仅保持变量的值(即指针)不变,如果要声明对象常量,则应该使用Object.freeze()。

块级作用域

由{}包裹的代码块。在for循环中,()与{}是父子块级作用域,也就是说{}用let或const声明的变量不会影响for循环计数。

块级作用域没有变量提升,可以防止在函数内使用上级变量时,后面声明的变量意外覆盖上级变量。

使用var声明变量:

js
var h=10;
function print(){
console.log(h)
var h;//覆盖了上级变量
}
print()//undefined

使用let声明变量:

js
var h=10;
function print(){
console.log(h)//暂时性死区
let h;//与当前作用域绑定,声明之前不可读取
}
print()//ReferenceError: Cannot access 'h' before initialization

同时块间的隔离有助于减少冲突和出错。此前,JS只能用函数作用域来隔离变量,常用的方式就是匿名立即执行函数(匿名IIFE)。

js
(function(){var hours=12}())
//等同于
{let hours=12}

暂时性死区 temporal dead zone

let和const声明的变量会与代码块绑定,在声明前不能使用同名的上级环境变量,否则会引发报错。

function

function关键字用于声明函数。

class ES6

class关键字用于声明类。

import ES6

import关键字用于导入其他模块的变量,这类变量被引用它的所有文件共享。

全局变量

var和function声明的全局变量会成为顶级对象(如window、global、self)的属性,而let、const、class、import不会。

判断变量是否存在

由于直接使用未声明的变量会报错,可以用try{}包裹代码,也可以用typeof variable == "undefined"判断。

命名规范

变量名由26字母的大小写、数字、“$“和”_“组成,不能用数字开头。甚至支持中文,但不建议使用,避免引发麻烦。

函数 Function

函数都是Function对象的实例,相比普通对象,函数多了可被调用的特征。

'Function'与‘function’的不同

‘Function’是JS的内置对象,而'function'是一个声明函数的关键字。

和其他语言函数的区别

由于JS是弱类型语言,函数无法指定形参类型与返回类型,同时也无法限制传入参数的个数,因此没有重载的特性。函数内部可以通过arguments对象获取实参。

函数声明

推荐使用函数表达式let func=()=>{}let func=function(){}为变量赋值,因此函数声明也遵循变量声明的规则。如果用function func(){}直接声明函数,ES5中函数声明能完整地提升,ES6虽然规定了行为类似let,但实际可能会先赋值为undefined,不同环境可能有不同的处理。

参数传递

JS中任何参数都只能通过值传递,不存在引用传参。传递对象时,实际上复制了“指针”。因而对指针本身做修改不会反映到对象上,指针只用于访问对象,但本身不是对象。

那些支持引用传参的语言,修改引用同时也会修改对象,这是JS和他们的不同。

对象 Obejct

属性

普通对象属性(数据属性)拥有4个描述符(Descriptor),分别是Configurable、Enumerable、Writable、Value,前三项默认值为true,Value默认值为undefined。

Configurable控制属性特性(包括getter与setter,但value除外)能否被修改、属性能否被delete,且只能从true变为false。Enumerable控制属性能否被for-in遍历。Writable和Value字面意思。

访问器属性拥有2-4个特性,分别是Configurable、Enumerable、Getter?、Setter?。getter和setter的作用与其他语言一致。

属性描述符通过Obejct.defineProperty()、Object.defineProperties()、Object.getOwnPropertyDescriptor()写入和读取。

运算符 Operator

比较运算符

== === > < >= <= != !==

==表示在类型转换后相等,===表示类型和值都一样。除非需要用到==的特性,否则建议用===比较。

比较对象

对象的比较与原始值不同,比较的是引用,因此两个完全相同的数组不相等,除非他们是对同一处的引用。

赋值运算符

+= /= *= -= %= 等

和其他语言用法相同。

'与'运算符

&&

‘与’运算符,如果左边表达式的值是false或可以转为false则返回左边表达式的值,否则返回右边表达式的值。

Boolean角度:&&只有当两边都为true,结果才为true,如果左边结果为false,右边不会判断。

'或'运算符

||

‘或’运算符,如果左边表达式的值是true或可以转为true则返回左边表达式的值,否则返回右边表达式的值。

Boolean角度:||只有当两边都为false,结果才为false,如果左边结果为true,右边不会判断。

扩展运算符ES6

...

ES6中的扩展运算符,用在数组或对象前表示取出所有项或属性。

用于对象

js
let obj={a:1,b:2}
let newObj={...obj,c:3}//{ a: 1, b: 2, c: 3 }

用于数组

赋值

生成数组的拷贝。

js
let arr=[0,1,2]
let newArr=[...arr,3,4]//[ 0, 1, 2, 3, 4 ]
let arr_copy=[...arr]
解构赋值

结合解构赋值,它还提供了生成数组的方法。

js
let [...arr_copy]=arr

let [ar1,...ar2]=[0,1,2,3]
ar1//0
ar2//[ 1, 2, 3 ]

let [...ar3,ar4]=[0,1,2,3]
//SyntaxError: Rest element must be last element

一个分号引发的惨案

js
let val = func()//;
[a,b]=[b,a] 或 [a[c],b[c]]=[b[c],a[c]]

如果缺少分号,JS解析会出现错误,原因是两行连在一起也符合语法规则。这种情况下

用于函数参数

除了为数组赋值,还支持作为函数参数。

js
let arr=[0,1,2]
function add(a,b){
  return a+b
}
add(...arr)//1

TIP

任何含Iterator接口的对象都可以通过扩展运算符转为真正的数组。详情见iterable接口

基本运算

! + - * / % ++ --

可以用于各种类型间的运算,不限于数字。

位运算符

<< >> ~ & |^ >>>

和其他语言用法相同。JS内部虽然存储64位数值,但对程序员透明,位运算符的结果和32位数值运算的结果一致。

三目运算符

expression1 ? expression2 : expression3

等同于

javascript
((expression1, expression2, expression3) => {
  if (expression1) {
    return expression2;
  } else {
    return expression3;
  }
})();

'expression'与'statement'

expression即表达式,是一段有值的语句,比如变量x,函数f或者其执行结果f()。其他语言中函数一般不能视作expression,但JS中函数是对象,这是特例。

statement意为声明,比如let a=10,或者if(code){code},这些语句不返回结果,而是提醒处理器该做什么。

方括号

[]

属性访问器。最常用的是表示数组[1,2,3]与数组下标arr[1],也可以作为对象的属性名obj['key'],支持使用变量作为属性名obj[key](key不仅可以是符合规则的字符串,也可以是Symbol)。

点运算符

.

属性访问器。点运算符的功能是[]的子集,当属性名为常量时可以用于设置、获取对象属性obj.key

循环体 Loop

while

while(expression){}

do...while

do{statement}while(expression)

forEach

Array.prototype.forEach(function(currentValue, index, arr), thisValue)

由于是以传入函数的形式遍历,forEach无法使用return从外部函数体返回,由于是数组的一种方法,也不支持break跳出循环。

for…in

for(let item in obj)

for…in支持遍历各种对象,它的item是对象的key,总是string类型。这种方法不稳定,不同时候结果的顺序可能不一致。如果用于数组,还有一个问题是所有属性也包括数组元素以外的自定义属性。

for…of ES6

for(let item of obj)

首先,它没有for…in的缺点,其次,也没有forEach的缺点。for…of支持数组、字符串、Set、Map和其他有iterable接口的对象,但不支持普通对象(会提示is not iterable)。

循环控制

在循环体中使用continue或break可以跳过一次循环/退出循环。对于嵌套循环结构,JS提供了label关键字标记循环。

label: statement

javascript
loop1: while (true) {
  loop2: while (true) {
    break loop1;
  }
}

控制语句 statement

If语句

if(expressionA){}else if(expressionB){}...else{}

Switch语句

switch(expression)case expression:statement break;...default:

部分关键字 Keywords

new

从构造函数派生出对象,构造函数的this指向创建的对象。

delete

用于删除对象属性,不可用于删除对象。

throw

抛出异常。通常结合try...catch使用。

async&yield

被异步函数的一种写法需要。作为语法糖可以被链式调用替代。

错误处理 Error Handling

try...catch语法

try...catch

js
try {
  //insert code here
  a.b=c
}
catch(err) {
  console.error("Error catched: "+err)
}

throw

抛出自定义错误。

js
try {
  throw 'Number is too big'
}
catch(err) {
  console.error(err)
}

finally

无论是否发生错误都会执行的语句。

js
try {
}
catch(err) {
}
finally {
}

Error对象与类型

如果是内置错误(非throw抛出),抛出的是一个Error对象。包括name和message属性。

错误类型(Error.name)触发条件
ReferenceError引用了尚未声明的变量。
SyntaxError语法错误。
TypeError类型错误。如xxx is not a function
URIErrorURI函数的独有报错。
rangeErrorNumber方法的独有报错。
EvalErroreval()

参考目录

  1. this https://www.cnblogs.com/xiaohuochai/p/5735901.html
  2. JavaScript https://www.liaoxuefeng.com/wiki/1022910821149312
  3. ECMA Script 6 http://es6.ruanyifeng.com/
  4. Execution Context https://juejin.im/entry/58edde2761ff4b00581b93ff
  5. Symbol https://www.cnblogs.com/diligenceday/p/5462733.html
  6. MDN
  7. runoob

用心去做高质量的内容网站,欢迎 star ⭐ 让更多人发现