《你不知道的JavaScript 中卷》
2017-01-15 21:50
113 查看
慢慢的,敢说自己懂 JS 了,坐等下卷
变量是没有类型的,只有值才有
JavaScript 中的变量是没有类型的,只有值才有,在对变量执行 typeof 操作时,得到的结果并不是该变量的类型,而是该变量持有的值的类型。类型是值的内部特征,它定义了值的行为。
所有的值都对应一个类型,JS 有 7 种内置类型
空值(null) 未定义(undefined) 布尔值(boolean) 数字(number) 字符串(string) 对象(object) 符号(symbol,ES6 新增)
typeof 查看值的类型
typeof undefined === 'undefined' typeof true === 'boolean' typeof 42 === 'number' typeof "42" === 'string' typeof {life: 42} === 'object' typeof Symbol() === 'symbol'
有一个特殊的
typeof null === 'object'
这是个 BUG。
函数和数组也是对象
typeof function a(){} === 'function'
但函数(function)并不是一个内置类型,它是 object 的一个『子类型』。它有一个内部属性[[call]],该属性使其可以被调用,函数是『可调用对象』。
typeof [1, 2, 3] === 'object'
数组也是 object 的一个『子类型』。数组的元素按数字顺序来进行索引(普通对象是通过字符串键值)。
undefined 和 undeclared
var a; a; // undefined b; // ReferenceError: b is not defined
a的值是
undefined,
b报错,但报错信息可能会误导人,
not defined并不是
undefined,而是
undeclared,直接使用
undeclared的变量会报错,然而,有一个特殊情况
var a; typeof a; // "undefined" typeof b; // "undefined"
typeof b没有报错,而是返回字符串
undefined!
访问不存在的对象属性也不会产生
ReferenceError错误。
没有真正意义上的整数
JavaScript 只有一种数值类型:number。没有真正意义上的整数
42.0 === 42; // true
数字前面的 0 可以省略
var a = 0.42; var b = .42;
小数部分最后面的 0 也可以省略
var a = 42.0; var b = 42.;
默认情况下大部分数字都以十进制显示,小数部分后面的 0 被省略
var a = 42.3000; var b = 42.0; a; // 42.3 b; // 42
特别大或特别小的数字默认用指数格式显示
var a = 5E10; a; // 50000000000 a.toExponential(); // "5e+10" var b = a * a; b; // 2.5e+21 var c = 1 / a; c; // 2e-11
数字常量也可以用
.运算符,但
.是一个有效的数字字符,会被优先识别为数字常量的一部分,然后才是对象属性访问运算符
42.toFixed(3); // SyntaxError,`.`被视为数字的一部分,所以没有属性访问运算符 // 下面的语法都有效 (42).toFixed(3); 0.42.toFixed(3); 42..toFixed(3); // 第一个`.`是数字的一部分,第二个`.`是属性访问运算符
十六进行
oxf3; oXf3;
八进制
0363;
ES6 严格模式不再支持上面的八进制形式,而是
0o363; 0O363;
ES6 还有二进制
ob11110011; oB11110011;
值复制(value-copy)和引用复制(reference-copy)
简单值(包括 null、undefined、字符串、数字、布尔和 symbol)总是通过值复制(value-copy)的方式来赋值/传递;复合型(对象,包括数组、函数、封装对象)总是通过引用复制(reference-copy)的方式来赋值/传递。
我们无法自行决定使用值复制还是引用复制,一切由值的类型决定。
var a = 2; var b = a; // b 是 a 的值的一个副本(值复制) b++; a; // 2 b; // 3 var c = [1, 2, 3]; var d = c; // d 是 [1, 2, 3] 的一个引用(引用复制) d.push(4); c; // [1, 2, 3, 4] d: // [1, 2, 3, 4]
a持有 2 的一个副本,
b持有 2 的另一个副本;
c和
d是指向 [1, 2, 3] 的两个不同的引用(不是持有)。
var a = [1, 2, 3]; var b = a; a; // [1, 2, 3] b; // [1, 2, 3] b = [4, 5, 6] a; // [1, 2, 3] b; // [4, 5, 6]
引用指向的是值本身而非变量,所以一个引用无法更改另一个引用的指向。
function foo(x) { x.push(4); x; // [1, 2, 3, 4] x = [4, 5, 6]; x.push(7); x; // [4, 5, 6, 7]; } var a = [1, 2, 3]; foo(a); a; // [1, 2, 3, 4]
其实,
值复制就是复制值,
引用复制就是复制引用。
没想到 parseInt 也有幺蛾子
parseInt(false, 16); // 250
parseInt 第一个参数要求是字符串,如果不是,则先转成字符串 ‘false’,按 16 进制解析为 fa = 250
|| 和 &&并不是返回判断结果
这个有点震惊,以前没有注意过,返回的是操作数中的其中一个a || b 的意思是
a ? a : b
a && b 的意思是
a ? b : a
比闭包还疯狂的来了 ——宽松相等
看了下面的运行结果才能体会到有多疯狂if ([0]) {console.log('true')} // true if ([0] == false) {console.log('true')} // true
第一行可以理解,因为 [0] 转成布尔就是 true,但是第二行呢?
根源就在于宽松相等 == 会发生类型转换,转换的规则是
布尔转数字 字符串转数字 对象转数字(valueOf())或字符串(toString()) null == undefined null !== undefined
所以,就可以理解第二行代码了,
[0] == false中的
[0]不是转成布尔 true,而是转成数字 0,右边的
false转成数字 0,所以
[0] == false的结果是 true。
但是有一个例外,也就是空字符串会转成数字 0
0 == ''; // true
和宽松相等一起疯狂的还有<、>、<=、>=
非字符串或数字会先转换成字符串或数字var a = {b: 42}; var b = {b: 43}; a == b; // false a > b; // false a < b; // false a <= b; // true a >= b; //true
==时并不发生转换,所以
a == b返回 false;
>或
<时 a 和 b 都转换成字符串
[object Object],所以都返回 false;
问题是
a <= b和
a >= b为什么返回 true,因为这里有个奇葩的地方
<= 的意思不是"小于等于",而是"不大于",即 > 的结果取反 >= 同样
语句的返回值
var a = 3; // undefined a = 3; // 3
所以,有下面这个样的赋值
var a = b = c = 3;
你以为的 else if 并不是 else if
if 只有一条语句时可以省略大括号if (a) { } else if (b) { } else { }
实际是
if (a) { } else { if (b) { } else { } }
所以,你以为的 else if 并不是 else if
switch 中的比较是严格相等
var a = 42; switch(a) { case '42': console.log('42!==\'42\''); break; case 42: console.log('42===42'); break; } // 42===42
相关文章推荐
- 你不知道的javascript-中卷
- JavaScript中的this(你不知道的JavaScript)
- 你不知道的javascript之JS原型对象和原型链
- 你不知道的JavaScript(一)数据类型
- 你不知道的JavaScript(三)字符串
- 你不知道的JavaScript--Item6 var预解析与函数声明提升(hoist )
- 你不知道的JavaScript--Item10 闭包(closure)
- 你不知道的JavaScript(八)逻辑运算
- 你不知道的JavaScript (上)
- 你不知道的JavaScript--Item20 作用域与作用域链(scope chain)
- 你不知道的javascript---词法作用域
- 你不知道的14种常用的javascript调试技巧
- JavaScript对象、函数(你不知道的JavaScript)
- 你不知道的javaScript笔记(1)
- 14个你可能不知道的JavaScript调试技巧
- 你可能不知道的一些JavaScript 奇技淫巧
- JavaScript词法作用域(你不知道的JavaScript)
- 你可能不知道的java、python、JavaScript以及jquary循环语句的区别
- 你不知道的JavaScript--Item28 垃圾回收机制与内存管理