JavaScript 语法简单,很多人都是上来看个例子就写,边搜索边写。所以很多基本的东西反而不是很了解。这里总结了一些东西希望有帮助。
变量名
变量名只能以字母和$_两个字符起始,非首字符还可以是数字。虽然变量名可以使用其他 unicode 字符,但是最好不要这么做。巨坑。
数据类型
JavaScript 是弱类型或叫动态类型。同个变量可以赋各种类型的值。感觉有点类似 c/c++ 的指针,可以指向任意类型。比如
var str = "a string";
str = 1; //原来是字符串,现在改为数值完全没有问题
str = [1, 'str',{'prop': 'val'}]; //改为数组也没有问题,而且一个数组可以保存不同类型的数据
发现每本讲 JavaScript 的书对其基本类型的分法都不一样。如果仅关心对变量求 typeof 的结果,这些结果只会是以下 6 种之一
1. number 数值。IEEE-754 double-precision (64 bit)
typeof 1;
typeof NaN; //"number",NaN(Not a Number 非数值) 后面有更多介绍
typeof Infinity; //也是 "number",无穷大
2. string 字符串。16 位 unicode
3. boolean 布尔。(1 bit)
4. object
typeof [1,2]; //数组对象
typeof {'s':1}; //字面量对象
typeof null; //空,对象的一种特殊形式。
5. undefined 未定义
6. function 函数
typeof function(){};//"function"
使用 typeof 的一点经验,曾经发现个 bug 是关于它的。类似如下:
var v1 = 4,
v2 = 2;
typeof v1*v2; //以为会是 number,其实返回 NaN。
typeof v1+v2; //返回 "number2"
看了后一个应该很容易理解,因为 typeof 的优先权(precedence)高于 * + 等运算符号,所以是 “number”*2,返回 NaN,“number” + 2 返回 “number2”。使用时注意。
null 和 undefined
一般申明一个暂时不用赋值的变量两者都可以,默认是 undefined。但是如果涉及到变量的最终目的是指向一个对象,而且最终要保存到数据库,可能 null 会更合适些,因为毕竟 null 算是对象,如果没有赋值,保存后数据库也会是 null,但如果是 undefined,数据库就可能收不到值。
他们之间的关系:
null == undefined //true
null === undefined //false; 具体见下面的操作符部分
前面说的 null 是一种特殊的对象,因为虽然它的 typeof 结果是 object,但是没有其他对象都具有的 6 个方法:
1. constructor() 用于创建对象的构造函数
2. hasOwnProperty() 用于检查给定的属性在当前对象实例中是否存在,这个检查不包括实例原型。其中作为参数的属性名 propertyName 必须是字符串形式。例如:o.hasOwnProperty("name")。
3. isPrototypeOf(object) 用于检查传入的对象是否是另一个对象的原型
4. propertyIsEnumerable(propertyName) 用于检查给定的属性是否能够使用for-in语句来枚举
5. toString() 返回对象的字符串表示
6. valueOf() 返回对象的字符串、数值或布尔值表示。通常与toString()方法的返回值相同。
NaN 和 Infinity
NaN 和 Infinity ( 还有下面提到的判断 NaN 的方法 isNaN())都是全局对象的属性和方法,所以可以直接使用。
NaN(Not a Number 非数值)其实很少用,一般都是数学计算失败的返回值,以免抛出错误。比如 Math.sqrt(-1) 和 parseInt(“str”) 都会返回 NaN。 不过有一个特殊情况就是除以零。非零数除以零返回Infinity,但是 0/0 返回 NaN。
console.log(0/0); //输出 NaN
console.log(2/0); //输出 Infinity
NaN 最坑人的就是
NaN == NaN
NaN === NaN //两个判断结果都是 false
其实这个非要解释也能说得通。 typeof NaN
返回 "number",所以 NaN 是一种 ”number“,当然 NaN !== NaN
就该为真了。或者说 NaN is not Not a Number。你感受下。
要预防判断变量出现 NaN !== NaN,可以使用 !! 双重否定来把任何变量转换为布尔类型比较。例如:!!NaN === !!NaN 就是 true,符合常人逻辑了。!! 是 Boolean() 的简化版。
还可以使用 isNaN() 来判断是否是 NaN。使用例子:
isNaN( NaN ); //true
isNaN( 7 ); //false
isNaN( "7" ); //也是false. 因为可以转化为数值 7
isNaN( "str" ); //true. 不能转化为数值
isNaN( true ); //false. 可以转化为数值 1
isNaN( null ); //false. 可以转化为数值 0
关于数值转化的更多规则可以看其他资料,比如 这篇里的 Number 类型.
操作符
唯一值得注意的 == 和 ===。
== 判断值相等;=== 判断值和类型都要相等。 例如:
10 == ”10“; //ture
10 === "10"; //false
另外,switch 是用的 ===。
if 判断
在程序里我们经常要使用条件语句来对变量进行比较和判断,这样就会涉及到各种数据类型转换为布尔值的规则。
在 JavaScript 里,以下会被转换为 false:
1. number 数值:0(包括-0) 和 NaN
2. string 字符串:"" 空字符串
3. boolean 布尔:false
4. object 对象:null
5. undefined 未定义:undefined
前面提到的 6 种 typeof 结果,只有其中的 5 项里的 6 个值会转换为 false。其他的都是 true。
在使用 if 时,如果期望为 true 的值是以上提到的 6 个值之外的任何值,就可以直接使用
if (var){ //没有必要使用 !!var;不过很多代码用 !!
//true
};
但是如果要判断两个值是不是一样再进行下一步操作,例如
if (var1 === var2){
}
为了避免前面在 NaN 部分讲的 NaN !== NaN 逻辑不一致情况,可以使用 !! 双重否定来把任何变量转换为布尔类型之后再作比较。比如
if (!!var1 === !!var2){ // !!NaN === !!NaN 返回 true
}
小结
- 使用 !!var1 === !!var2 来判断变量是否相等. !! 是预防 NaN 出现违反逻辑。
- JavaScript 一共有 6 个可转换为假的值 :0 (-0); NaN; ""; false; null; undefined. 可以直接用 if(var) 来对变量进行判断。
转一个刚看到的帖子,关于 js 的字符串与数值计算: http://www.reddit.com/r/ProgrammerHumor/comments/2ubhql/please_dont_hate_me_javascript_devs/
> '5' - 3
2 // weak typing + implicit conversions = headaches
(弱类型 + 隐含转换 = 头疼)
> '5' + 3
'53' // Because we all love consistency
(因为我们都爱一致性)
> '5' - '4'
1 // string - string = integer. what?
(字符串 - 字符串 = 整型。什么?)
> '5' + + '5'
'55'
> 'foo' + +'foo'
'fooNaN' // Marvelous.
(妙不可言)
> '5' + - '2'
'5-2'
> '5' + - + - - + - - + + - + - + - + - - - '-2'
'52' // Apparently it's ok
(显然很好)
> var x = 3;
> '5' + x - x
50
> '5' - x + x
5 // Because fuck math
(因为滚他妈的数学)
var v1 = 4,
v2 = 2;
typeof v1*v2; //以为会是 number,其实返回 NaN。
typeof v1+v2; //返回 "number2"
这个好坑,还有最后写的,太绕了…