1. JavaScript 程序的执行单位为行(line),也就是一行一行地执行。
2. JavaScript 的变量名区分大小写,A
和a
是两个不同的变量。
3. 变量的声明和赋值,是分开的两个步骤。如果只是声明变量而没有赋值,则该变量的值是undefined
。
4. JavaScript 是一种动态类型语言,也就是说,变量的类型没有限制,变量可以随时更改类型。
5. JavaScript 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting)。
6. 标识符的命名规则:
- 第一个字符,可以是任意 Unicode 字母(包括英文字母和其他语言的字母),以及美元符号(
$
)和下划线(_
)。 - 第二个字符及后面的字符,除了 Unicode 字母、美元符号和下划线,还可以用数字
0-9
。
注:中文是合法的标识符,可以用作变量名。
7. 关于注释:由于历史上 JavaScript 可以兼容 HTML 代码的注释,所以<!--
和-->
也被视为合法的单行注释。-->
只有在行首,才会被当成单行注释,否则会当作正常的运算。
function countdown(n) {
while (n --> 0) console.log(n);
}
countdown(3)
// 2
// 1
// 0
上面代码中,n --> 0
实际上会当作n-- > 0
,因此输出2、1、0。
8. switch
语句后面的表达式,与case
语句后面的表示式比较运行结果时,采用的是严格相等运算符(===
),而不是相等运算符(==
),这意味着比较时不会发生类型转换。
9. JavaScript 有三种方法,可以确定一个值到底是什么类型。
typeof
运算符instanceof
运算符Object.prototype.toString
方法
typeof
运算符可以返回一个值的数据类型。数值、字符串、布尔值分别返回number
、string
、boolean
。函数返回function
。undefined
返回undefined
,typeof
可以用来检查一个没有声明的变量,而不报错。对象返回object
。null
返回object
。
instanceof
运算符可以区分数组和对象。
10. 转换规则是除了下面六个值被转为false
,其他值都视为true
。
undefined
null
false
0
NaN
""
或''
(空字符串)
11. JavaScript 内部,所有数字都是以64位浮点数形式储存,即使整数也是如此。所以,1
与1.0
是相同的,是同一个数。
1 === 1.0 // true
JavaScript 对15位的十进制数都可以精确处理。
12. 几乎所有场合,正零和负零都会被当作正常的0
。唯一有区别的场合是,+0
或-0
当作分母,返回的值是不相等的。
(1 / +0) === (1 / -0) // false
上面的代码之所以出现这样结果,是因为除以正零得到+Infinity
,除以负零得到-Infinity
,这两者是不相等的。
13. NaN
不是独立的数据类型,而是一个特殊数值,它的数据类型依然属于Number。
14. 如果长字符串必须分成多行,可以在每一行的尾部使用反斜杠。
var longString = 'Long \
long \
long \
string';
longString
// "Long long long string"
15. 无法改变字符串之中的单个字符。字符串内部的单个字符无法改变和增删,这些操作会默默地失败。
var s = 'hello';
delete s[0];
s // "hello"
s[1] = 'a';
s // "hello"
s[5] = '!';
s // "hello"
16. 查看一个对象本身的所有属性,可以使用Object.keys
方法。
var obj = {
key1: 1,
key2: 2
};
Object.keys(obj);
// ['key1', 'key2']
17. delete
命令只能删除对象本身的属性,无法删除继承的属性。
var obj = {};
delete obj.toString // true
obj.toString // function toString() { [native code] }
18. 将数组清空的一个有效方法,就是将length
属性设为0。
19. 典型的“类似数组的对象”是函数的arguments
对象,以及大多数 DOM 元素集,还有字符串。数组的slice
方法可以将“类似数组的对象”变成真正的数组。
var arr = Array.prototype.slice.call(arrayLike);
除了转为真正的数组,“类似数组的对象”还有一个办法可以使用数组的方法,就是通过call()
把数组的方法放到对象上面。
function print(value, index) {
console.log(index + ' : ' + value);
}
Array.prototype.forEach.call(arrayLike, print);
注意,这种方法比直接使用数组原生的forEach
要慢,所以最好还是先将“类似数组的对象”转为真正的数组,然后再直接调用数组的forEach
方法。
20.
var f = function () {
console.log('1');
}
function f() {
console.log('2');
}
f() // 1
21. 函数的name
属性返回紧跟在function
关键字之后的那个函数名。
函数的length
属性返回函数预期传入的参数个数,即函数定义之中的参数个数。(不管调用时输入了多少个参数)
length
属性提供了一种机制,判断定义时和调用时参数的差异,以便实现面向对象编程的”方法重载“(overload)。
函数的toString
方法返回一个字符串,内容是函数的源码。(函数内部的注释也可以返回。)
22.函数参数如果是原始类型的值(数值、字符串、布尔值),传递方式是传值传递(passes by value)。
这意味着,在函数体内修改参数值,不会影响到函数外部。
但是,如果函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递(pass by reference)。
也就是说,传入函数的原始值的地址,因此在函数内部修改参数,将会影响到原始值。
注意,如果函数内部修改的,不是参数对象的某个属性,而是替换掉整个参数,这时不会影响到原始值。
var obj = [1, 2, 3];
function f(o) {
o = [2, 3, 4];
}
f(obj);
obj // [1, 2, 3]
23.严格模式下,arguments
对象是一个只读对象,修改它是无效的,但不会报错。
arguments
对象带有一个callee
属性,返回它所对应的原函数。
var f = function () {
console.log(arguments.callee === f);
}
f() // true