# 基础语法

# 一、基本概念

  • 区分大小写:ECMAScript 一切(变量、函数名、操作符)都是 区分大小写 的;例如:testTest变量不是同一个变量,typeOf 可作为函数名,但 typeof 是关键字不能作为函数名。

  • 标识符:指变量、函数、属性、参数的 名字;可以是一个或多个字符组合,但 第一个字符不能是数字,其他情况下可用 字母、下划线、美元符号、数字;建议采用 驼峰写法,即第一个字母小写后面单词首字母大写,其实 全部使用小写也可以(不太规范)

  • 注释

    // 单行注释
    /*
     * 多行注释(为了提高可读性,多行注释前都带上*)
     */
    
    1
    2
    3
    4
  • 严格模式:ECMAScript5 提出的,对 3 版本的不确定行为加以处理,不安全的操作也会抛错,写法:

    function doSomething() {
      "use strict";
      // 其他内容
    }
    
    1
    2
    3
    4
  • 语句:每句后面可以没有分号,但要是压缩代码就会出错,所以 推荐加上分号,if 语句后推荐使用{},即使只有一句,这样可以提高代码的可读性。

  • 关键字:具有特定用途,不能作为标识符。breakcasecatchcontinuedefaultdeletedoelsefinallyforfunctionifininstanceofnewreturnswitchthisthrowtrytypeofvarvoidwhilewithdebugger

  • 保留字:将来可能被用作关键字,也不能作为标识符

    • 第 3 版保留字:abstractbooleanbytechardoublefinalfloatgotointlongnativeshortsynchronizedthrowstransientvolatile
    • 第 5 版严格模式下保留字:implementsinterfacepackageprivateprotectedpublicstaticletyield
    • 第 5 版非严格模式下保留字:classconstenumexportextendsimportsuper

# 二、变量声明

js 的变量可以用来保存任何类型的数据(松散类型),例如:

var message = "hi",
  found = false,
  age = 29;
1
2
3
  • 不推荐修改变量所保存值的类型,实际上是可以的;
  • 不推荐省略 var,虽然省略 var 可以作为全局变量,但很难维护,并且未经声明的变量赋值在严格模式抛 ReferenceError 错误;
  • 严格模式下变量名不要取“eval”和“argument”。

# 三、数据类型

  • ECMAScript 有 6 种数据类型,其中 undefined、null、boolean、number 和 string 是简单(基本)数据类型,剩下的 Object 是一种复杂数据类型。
  • 因 ECMAScript 的变量是松散类型,我们可用 typeof 操作符 来检测变量的数据类型,写法:typeof messagetypeof(message)。它会返回这些字符串:"undefined""boolean""string""number""object""function"

# 3.1 undefined 和 null

var message; // 这里相当于var message = undefined;
console.log(message == undefined); // true。message === null的结果就是false,因为此时message就是undefined
console.log(typeof age); // "undefined"

var car = null; // 常规写法,声明变量一般都会初始化,不知道赋什么那就赋个null也是可以的
console.log(typeof car); // "object"。null值表示空对象指针,它实际上是个object类型
console.log(null == undefined); // true。undefined派生自null,但这只是出于比较的目的
1
2
3
4
5
6
7

事实上 null 和 undefined 完全不同,我们没有必要将变量显式设为 undefined,若要展示保存而未知其值可以 null 临时将其保存,所以不推荐var message;这种写法,可以var message = null;

# 3.2 boolean

布尔类型 Boolean:只有两个字面量,true(真)和false(假)。

任何数据类型的值调用Boolean()函数都会返回一个 Boolean 值:

Boolean() 转换为 true 值 转换为 false 值
String 任何非空字符串 ""(空字符串)
Number 任何非零数值(包含无穷大) 0 和 NaN(非数值)
Object 任何对象 null
Undefined n/a 或 N/A(not applicable) undefined

流控制语句(例如 if 语句)会自动执行相应的 Boolean 转换

var message = "hello world";
if (message) {
  // 非空字符串转换为true值
  console.log("Value is true");
}
1
2
3
4
5

# 3.3 number

该类型比较受关注,用 IEEE754 格式来表示 整数和浮点数值,ECMA-262 定义了 十进制、八进制、十六进制 三种数字字面量格式。
其中八进制在严格模式下是无效的;在非严格模式下类似 079、08 会被解析成十进制的 79 和 9;另外十六进制 A-F 可大写也可小写。

# 3.3.1 浮点数值

  • 该数字要有一个小数点且小数点后至少要有一个数值,但不推荐.1这种写法,即不要省略整数位;
  • 为节省内存1.10.0这样的值会被转换为整数;
  • 对极大或极小值通常用科学计数法,像 0.0000003 在默认情况下(带 6 个零及以上的浮点数)自动转化为 e 表示法;
  • 需要注意的一点,由于 IEEE754 浮点计算通病0.1+0.2是等于0.30000000000000004(17 为小数),0.05+0.250.15+0.15不会出现问题,不要直接加,可以使用精度来转化。

# 3.3.2 数值范围

  • Number.MIN_VALUE:能表示的最小数值,通常是 5e-324;
  • Number.MAX_VALUE:能表示的最大数值,通常是 1.7976931348623157e+308;
  • Number.NEGATIVE_INFINITY:-Infinity 负无穷
  • Number.POSITIVE_INFINITY:Infinity 正无穷

isFinite()函数在参数位于最小与最大数值之间时会返回 true,例如:

var result = Number.MAX_VALUE + Number.MAX_VALUE;
console.log(isFinite(result)); // false
1
2

# 3.3.3 NaN

NaN是非数值(Not a Number),表示一个本来要返回数值的操作数但未返回数值的情况。

有两个特点:

  • 任何涉及 NaN 的操作(例如NaN/10)都会返回NaN
  • NaN与任何值都不相等,包括NaN本身,NaN == NaN为 false。

针对这两个特点定义了isNaN()函数,判断参数是否“不是数值”,函数拿到这个入参时会将这个值 尝试转换为数值,其实调用的是Number()函数。

# 3.3.4 数值转换

使用parseInt()parseFloat()可以把字符串转化为 整数浮点数

而使用Number()可以将任何数据类型转化为数值,其规则是:

  • 如果是 Boolean 值,true 将被转换为 1,false 将被转换为 0;
  • 如果是 null 值,返回 0,如果是 undefined,返回 NaN;
  • 如果是字符串:
    • 有效浮点格式的字符串会被转换为浮点数;
    • 整数型的字符串八进制的不会被视为八进制(011会转换为11),只会将十六进制和十进制格式的字符串转换为相等大小的十进制整数数值;
    • 空字符串""转换为 0;
    • 其他情况的字符串会转换为 NaN;
  • 如果是对象,先调用对象的valueOf()再按照上述规则转换,然后若得到 NaN 就去调用toString()再按照上述规则转换
Number("hello"); // NaN
Number(""); // 0
Number(true); // 1
1
2
3

可以看出Number()在转化字符串时比较复杂,我们推荐parseInt()来处理整数格式的字符串

  • parseInt()在接卸字符串时会忽略前面的空格,直到找到 第一个数字或负号,也就是说 parseInt()在字符串还是 非整数格式空字符串 时会返回 NaN;
  • 在找到一个数字字符后会继续解析直到遇到 非数字字符
  • 由于 ECMAScript 3 和 5 对八进制字面量解析时存在分歧,所以我们会推荐使用 基数 来指明是按几进制来解析。
parseInt("   1234blue"); // 1234
parseInt(""); // 空字符串使用parseInt()会解析成NaN,而Number()是0
parseInt("0xAF", 16); // 按基数16来解析,175
parseInt("AF"); // 基数16和0x必须要有一个,NaN
parseInt("10", 2); // 按二进制解析,结果为2,我们非常推荐使用这种写法
1
2
3
4
5

# 3.4 String 类型

String 类型用于表示由零或多个 16 位 Unicode 字符组成的字符串。

# 3.4.1 转义序列

\n换行,\t制表,\b退格,\r回车,\f进纸,\\斜杠,\'单引号,\"双引号,
\xnn 以十六进制代码 nn 表示的一个字符(其中 n 为0~F),例如\x41表示A
\unnnn 以十六进制代码 nnnn 表示的一个 Unicode 字符(其中 n 为0~F),例如\u03a3表示Σ
其中 4 个字符长的转义序列和 6 个字符长的转义序列在字符串中只占 1 位。

# 3.4.2 字符串的特点

字符串的值是不可变的,有些例子看起来是可变,其实原字符串销毁新字符串创建是在后台完成的。

# 3.4.3 字符串转换

将一个值转换成字符串有两种方式,第一种是使用几乎每个值都有的toString()方法:

var age = 11,
  num = 10;
age.toString(); // "11"
num + ""; // "10"
1
2
3
4

toString()方法也可以使用基数:

var num = 10;
num.toString(2); // "1010"
1
2

null 和 undefined 值是没有 toString()方法的,那么可以使用字符串转换的第二种方式String(),其规则是:传入的值有 toString()则会调用 toString(),若传入的值是 null、undefined 则返回"null""undefined"这样的字符串。

其实转化为字符串有种更快捷的方法就是xxx + ""

# 3.5 Object 类型

ECMAScript 中的对象其实就是一组 数据和功能 的集合。对象可以通过执行 new 操作符后跟要创建类型的名称来创建。Object 类型是所有它的实例的基础,它所具有的属性和方法在更具体的对象中同样存在。

Object 的每个实例都具有以下属性个方法:

  • constructor:构造函数;
  • hasOwnProperty(propertyName):用于检查给定的属性在当前对象实例中是否存在,而不是在实例的原型中;
  • isPrototypeOf(object):用于检查传入的对象,是否是当前对象的原型;
  • propertyIsEnumerable(propertyName):用于检查给定的属性是否能使用 for-in 枚举;
  • toLocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应;
  • toString():返回对象的字符串表示;
  • valueOf():返回对象的字符串、数值或布尔值,通常与toString()方法的返回值相同。

# 四、操作符

可以操作字符串、数值、布尔值、对象(调 valueOf()和 toString())

# 4.1 一元操作符

只能操作一个值。

# 4.1.1 递增和递减操作符

分为前置型和后置型。

var num1 = 2,
  num2 = 20;
var num3 = --num1 + num2; // 等于21,前置型会先自己“减减”再去参与外界计算
var num4 = num1++ + num2; // 等于21,上一步num1为1,这一步是先参与外界计算,后才自己去“加加”
1
2
3
4

上述对于数值,对于 其他类型也可用,只是自动调用了Number()函数,再去操作“++”、“--”

# 4.1.2 一元加和一元减操作符

加号(+)放在数值前面对数值没有影响,而一元减相当于添加了符号。在一元加和一元减对非数值应用时跟一元操作符类似也调用了Number()函数。

var s1 = "01";
s1 = -s1; // s1的值变为了 -1
var s2 = "1.1";
s2 = -s2; // s2的值变为了 -1.1
var s3 = "z";
s3 = -s3; // s3的值变为了 NaN
var b = false;
s2 = -s2; // b的值变为了 0
var f = 1.1;
f = -f; // f的值变为了 -1.1
var o = {
  valueOf: function () {
    return -1;
  },
};
o = -o; // o的值变为了 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 4.2 位操作符

  • ECMAScript 中所有数字都以 64 位格式存储,但位操作符是操作 32 位格式的,所以操作前后是转换的;第 32 位是符号位:0 表示正数,1 表示负数;
  • 负数在二进制中是以“二进制补码”格式存储的,计算补码的步骤:
    • 求这个数值绝对值的二进制码
    • 求二进制反码
    • 在二进制反码上加 1
  • 而 ECMAScript 会尽力隐藏这些信息,一般是将这个负数的绝对值的二进制码前加一个负号,例如:var num = -18; num.toString(2); // “-10010”
  • NaN 和 Infinity 值应用位操作符时会被当成 0 处理,而对于非数值应用操作符会先用Number()函数将值转化为数值(自动完成的),后再用位操作符。

# 4.2.1 按位非(NOT)

按位非操作符由一个波浪线(~)表示,按位非歧视就是求反码。

var num1 = 25;
var num2 = ~num1; // 等价于 var num2 = -num - 1;即操作数的负值减1
console.log(num2); // -26   ~在底层执行速度要更快
1
2
3

# 4.2.2 按位与(AND)

按位与操作符由一个和号(&)表示,它有两个操作数。
按位与操作只在两个数值的对应位都是 1 时才返回 1,任意一位是 0 都返回 0。

# 4.2.3 按位或(OR)

按位或操作符由一个竖线(|)表示,它也有两个操作数。
按位或操作在两个数值的对应位至少有一个 1 就可返回 1,都是 0 才返回 0。

# 4.2.4 按位异或(XOR)

按位异或操作符由一个插入符号(^)表示,它也有两个操作数。
按位异或操作在两个数值的对应位不同时返回 1,都是 1 或都是 0 才返回 0.

# 4.2.5 左移

左移操作符由两个小于号(<<)表示,符号右侧是要向左移的位数。
这个左移不会影响操作数的符号位,2 左移 5 位是 64,而-2 就是-64。

# 4.2.6 有符号的右移

有符号的右移操作符由两个大于号(>>)表示,它右移空出的位置是用符号位的值来填充的。

# 4.2.7 无符号右移

无符号右移操作符由 3 个大于号(>>>)表示面对整数来说>>>>>结果相同。但对负数来说,右移空出的位置是用 0 填充的不再是符号位(负数符号位是 1)。

var value1 = -64; // 二进制11111111111111111111111111000000
var value2 = value1 >> 5; // 二进制11111111111111111111111111111110
var value3 = value1 >>> 5; // 二进制00000111111111111111111111111110
1
2
3

# 4.3 布尔操作符

# 4.3.1 逻辑非

逻辑非操作符由一个叹号(!)表示,其实它相当于先调用Boolean()函数再取反,而!!""里的两个!就相当于Boolean()了,Boolean()函数转换规则可以参考之前的3.2 boolean

# 4.3.2 逻辑与

逻辑与操作符由两个和号(&&)表示,有两个操作数,真值表类似按位与。

  • 如果第一个操作数是对象或第一个操作数(可能是表达式)求值结果为 true 时,它会返回第二操作数,否则返回一个操作数;
  • 如果第一个操作数就是 null、NaN、undefined,就直接返回 null、NaN、undefined;
  • 如果第一个操作数结果为 true 或对象,第二个操作数不能是未定义,否则会报错。

# 4.3.3 逻辑或

逻辑或操作符由两个竖线符号(||)表示,有两个操作符,真值表类似按位或。

  • 如果第一个操作数是空对象(null)或第一个操作数(可能是表达式)求值结果为 false,会返回第二个操作数,否则返回第一个操作数;
  • 如果两个操作数都是 null、NaN、undefined,则返回 null、NaN、undefined;
  • 如果第一个操作数结果为 false 或空对象(null),第二个操作数不能是未定义的,否则会报错。

# 4.4 乘性操作符

ECMAScript 定义了 3 个乘性操作符:乘法、除法和求模。操作数为非数值时会自动调用Number()函数来转换。

# 4.4.1 乘法

乘法操作符由一个星号(*)表示,特殊规则:

  • 如果有一个操作数是 NaN,则结果是 NaN(之前小节里有说过);
  • 如果 Infinity 与 0 相乘,则结果是 NaN(数学上规定∞ * 00/0∞/∞是没有意义的,计算不出来);
  • 如果 Infinity 与非 0 数值相乘,结果是 Infinity 或-Infinity;
  • 如果 Infinity 与 Infinity 相乘,结果是 Infinity。

# 4.4.2 除法

除法操作符由一个斜线符号(/)表示,特殊规则:

  • 如果有一个操作数是 NaN,则结果是 NaN(之前小节里有说过);
  • 如果零被零除,则结果是 NaN(数学上规定∞ * 00/0∞/∞是没有意义的,计算不出来);
  • 如果是非 0 数值被零除,结果是 Infinity 或-Infinity;
  • 如果是 Infinity 被 Infinity 除,结果是 NaN。

# 4.4.3 求模

求模(余数)操作符由一个百分号(%)表示,特殊规则:

  • 如果被除数是无穷大而除数是有限大的数字,则结果是 NaN;
  • 如果被除数是有限大的数值而除数是 0,则结果是 NaN;
  • 如果是 Infinity 被 Infinity 除,则结果是 NaN;
  • 如果被除数是有限大的数值而除数是无穷大的数值,结果是被除数;

# 4.5 加性操作符

# 4.5.1 加法

加法操作符(+)的用法:

  • 如果有一个操作数是 NaN,则结果是 NaN(之前小节里有说过);
  • 同号的 Infinity 相加结果还是同号的 Infinity;
  • 异号的 Infinity 相加则是 NaN;
  • 同号 0 相加还是同号 0(结果与第一个操作数保持一致);
  • 异号 0 相加却是+0
  • 如果其中一个操作数是字符串,另一个操作数是对象、数值或布尔值就会自动调用toString()方法取得字符串值并进行拼接,但另一个操作数是 null、undefined 则会自动调用String()函数取得字符串并进行拼接。
  • 如果操作数为对象({})或者是数组([])这种复杂的数据类型,那么就将两个操作数都转换为字符串,进行拼接

隐式转换面试题:

[] + []; // []转化为字符串是"",有最后拼起来结果就是""
[] + {}; // []转化为字符串是"",{}转化为字符串是"[object Object]",所有最后拼起来结果就是"[object Object]"
{
}
+[]; // 编译器将开头的{}理解为空代码块,那么这里“{} + []”相当于“+[]”,又相当于“Number([])”,那结果就是0;有些编译器会高级一点那就跟“[] + {}”结果一样是"[object Object]"
{
}
+{}; // 跟上面同样道理,相当于“+{}”又相当于Number({}),其结果就是NaN;有些编译器就是两个{}的字符串的拼接,其结果是"[object Object][object Object]"
1
2
3
4
5
6
7
8

JS 的{} + {}与{} + []的结果是什么? (opens new window)

# 4.5.2 减法

减法操作符(-)的用法:

  • 如果有一个操作数是 NaN,则结果是 NaN(之前小节里有说过);
  • 同号的 Infinity 相减则是 NaN;
  • 异号的 Infinity 相减是 Infinity,符号视情况而定;
  • 同号 0 相减是+0;异号 0 相减结果与第一个操作数保持一致;
  • 如果其中一个操作数是字符串、布尔值、null、undefined,则先调用 Number()函数转换为数值再执行减法计算,担忧一个操作数是对象,则会调用 valueOf()方法,如果没有 valueOf()方法则会调用 toString()得到字符串再转化为数值去计算。

# 4.6 关系操作符

小于(<)、大于(>、小于等于(<=)、大于等于(>=,相应规则:

  • 如果一个操作数是数值,则将另一个操作数转换为一个数值;
  • 如果一个操作数是对象,则调用这个对象的 valueOf()方法,如果没有 valueOf()方法则调用 toString()方法;
  • 如果两个操作数都是字符串,则比较两个字符串对应位置的字符编码值。
var result = "Brick" < "alphabet"; // true,B的字符编码是66,a的字符编码是97
var result = "Brick".toLowerCase() < "alphabet".toLowerCase(); // false,都转换为小写,b的字符编码大于a的
var result = "23" < "3"; // true,因为先比较第一位也就是"2"比"3"
var result = "23" < 3; // false,如果一个操作数是数值,则将另一个操作数转换为一个数值
var result = "a" < 3; // false,任何操作数与NaN进行关系比较时,其结果都为false
1
2
3
4
5

# 4.7 相等操作符

# 4.7.1 相等和不相等

两个等于号(==)表示相等操作符,叹号后跟等于号(!=)表示不相等操作符,这两个操作符都会先转换操作数(强制转型),然后再比较他们的相等性。

  • 如果一个操作数是数值,另一个操作数是布尔值或字符串会先调用 Number()函数转换成数值去比较相等性;
  • null 和 undefined 比较相等性,是相等的,他们比较时没有去转换换成数值的;
  • 如果有一个操作数是 NaN,不管第二个操作数还是不是 NaN,其相等操作符都会返回 false,不相等操作符返回 true(NaN 不等于 NaN);
  • 如果两个操作数都是对象,则比较他们是不是同一个对象,如果两个操作数都指向同一个对象,则相等操作符返回 true,否则返回 false。

# 4.7.2 全等和不全等

三个等于号(===)表示全等操作符,叹号后跟两个等于号(!==)表示不全等操作符,这两个操作符不但不转换操作数并且会先比较类型是否相同再比较相等性。null == undefined 返回 true,null === undefined 返回 false。

# 4.8 条件操作符

也是三元运算符xxx ? xxx : xxx,例如:var max = (num1 > num2) ? num 1 : num2;如果 num1 大于 num2,那就返回中间 num1 的值,否则返回最后一个 num2 的值。

# 4.9 赋值操作符

*=/=%=+=-=<<=>>=>>>=,主要是简化写法,其实没有任何性能的提升。

# 4.10 逗号操作符

可以执行多个操作、赋值

var num1 = 1,
  num2 = 2,
  num3 = 3;
var num = (5, 1, 4, 8, 0); // num的值为0
1
2
3
4

# 五、语句

# 5.1 if 语句

if (i > 25) {
  console.log("Greater than 25.");
} else {
  console.log("Less than or equal to 25.");
}
1
2
3
4
5

推荐使用代码块,即使只有一行代码执行

# 5.2 do-while 语句

var i = 0;
do {
  i += 2;
} while (i < 10); // i 小于10就会继续循环
console.log(i);
1
2
3
4
5

不管表达式的结果如何,循环体内的代码至少会执行一次

# 5.3 while 语句

var i = 0;
while (i < 10) {
  i += 2;
}
1
2
3
4

只有表达式结果为 true 时才会去执行循环体内的代码

# 5.4 for 语句

var count = 10;
for (var i = 0; i < count; i++) {
  console.log(i);
}
console.log(i); // 10
1
2
3
4
5

有三个表达式“初始化语句”、“循环条件”、“每执行完一次后的更变语句”。
由于 ECMAScript 中不存在 块级作用域,因此在循环内部定义的变量也可以在外部访问到。

# 5.5 for-in 语句

for (var propName in window) {
  document.write(propName);
}
1
2
3

精准的迭代语句,可以用来枚举对象的属性,对 null 和 undefined 使用 for-in 会报错,所以使用前要判断对象是否为 null 或 undefined。

# 5.6 label 语句

在代码中添加标签,一遍将来使用,一般与 break 或 continue 配合使用

var a = 0;
label1: for (var i = 0; i < 10; i++) {
  for (var j = 0; j < 20; j++) {
    a = i + "," + j;
    if (i === 3 && j === 2) {
      break label1;
    }
  }
}
console.log(a);
1
2
3
4
5
6
7
8
9
10

# 5.7 break 和 continue 语句

break 语句会立即退出这一层的循环(这层的 for 循环),而 continue 是立即退出本次循环(for 循环里会循环好几次,跳出这一次的)。

# 5.8 switch 语句

switch (i) {
  case 25:
    console.log(25);
    break;
  case 35:
    console.log(35);
    break;
  case 45:
    console.log(45);
    break;
  default:
    console.log("other");
}
1
2
3
4
5
6
7
8
9
10
11
12
13

case 里要是不带 break 的话,就会继续执行后面的 case;default 相当于 else 它不需要 break; switch 语句可以使用任何数据类型,case 的值可以是变量或表达式; switch 去比较使用的是全等“===”; 它在一些情况下可以替代if () {} else if () {} else {}这样逻辑。

# 六、函数

ECMAScript 中的函数使用 function 关键字来声明,后跟一组参数及函数体。

function sagHi(name, message) {
  console.log("Hello " + name + "," + message);
}
sagHi("Nicholas", "how are you today?"); // "Hello Nicholas,how are you today?"
1
2
3
4

任何函数都可使用 return 语句跟要返回的值来实现函数返回某值,并且函数都不需要定义返回值类型,return;后的语句是不可能再执行的

严格模式对函数有一些限制:

  • 不能把函数或参数名取为evalarguments
  • 不能出现两个命名参数同名的情况。

# 6.1 理解函数

ECMAScript 函数有一个重要特点:命名的参数只提供便利,但不是必须的。意思是函数命名的参数只是为了告诉外部我大概需要几个什么样的参数,实际上调用函数时解析器不会拿传参和命名时的参数去做比较,不关心你传进来几个参数也不关心类型,只会把你的入参放在类似数组的 arguments 对象中,可以通过 arguments[n]来访问第 n 个参数可以通过 length 属性来确定多少个参数传进来了。

function doAdd() {
  if (arguments.length == 1) {
    console.log(arguments[0] + 10);
  } else if (arguments.length == 2) {
    console.log(arguments[0] + arguments[1]);
  }
}
doAdd(10); // 20
doAdd(30, 20); // 50
1
2
3
4
5
6
7
8
9

这个特性算不上完美的重载,但也足够弥补 ECMAScript 的这一缺憾了。

function doAdd(num1, num2) {
  arguments[1] = 10;
  console.log(arguments[0] + num2);
}
1
2
3
4

每次执行 doAdd()函数都会重写第二个参数,arguments[1]和 num2 的值都会变为 10,但他们的内存空间是独立只是值同步。如果 num2 在外部没有传值进来时是赋予的 undefined。还有严格模式下 arguments 的值不能被重写。

# 6.2 没有重载

  • 重写 子类覆盖父类的方法(返回值和形参都不能改变,方法体改变了,也就是核心变了),在 js 里重写是可以的。
  • 重载:在同一个类里(执行环境),方法名相同而形参列表和方法体不一样的函数叫重载,这在 js 里是不存在的。
  • 因为 js 里使用 var 和 function 这样的关键字来声明 同名变量 时,都会以最后一个声明为准,它会覆盖之前所有 同名 的声明;js 里的同名函数的声明就是重载的写法,因为在同一个执行环境里,但由于同名的会被覆盖,那么 js 里没有函数重载这一说法。
function addSomeNumber(num) {
  return num + 100;
}
function addSomeNumber(num) {
  return num + 200;
}
var result = addSomeNumber(100); // addSomeNumber被定义了2次,后定义的会覆盖先定义的
1
2
3
4
5
6
7