L3F.WIN

Github及Hexo的使用

0%

《你不知道的JavaScript》中卷读书笔记第一部分

第1章 类型

Javascript的类型包括 Undefined, Null, Boolean, String, Number, Object

内置类型

  1. 空值(null)
  2. 未定义(undefined)
  3. 布尔值(boolean)
  4. 数字(number)
  5. 字符串(string)
  6. 对象(object)
  7. 符号(symbol, ES6中新增)

除对象外,其他统称为“基本类型”
我们可以通过typeof运算符来查看值的类型。

1
2
3
4
5
6
7
console.log( typeof undefined );    //undefined
console.log( typeof null ); //object
console.log( typeof true ); //boolean
console.log( typeof 42 ); //number
console.log( typeof "42" ); //string
console.log( typeof {life: 42} ); //object
console.log( typeof Symbol() ); //symbol

(null的类型为object,这是一个历来以久的bug)

值和类型

Javascript中的变量是没有类型的,只有值才有。变量可以随时持有任何类型的值。

第2章 值

数组

在Javascript中,数组可以容纳任何类型的值,而且不需要预先设置数组大小。

1
2
3
4
5
6
7
var a = [];
console.log( a.length ); //0

a[0] = 1;
a[1] = "2";
a[2] = [3];
console.log( a.length ); //3

(使用delete运算符可以将单元从数组中删除,但是删除后length属性并不会发生改变)
类数组
可以通过indexOf(), concat(), forEach(), Array.from()来讲类数组转换成为真正的数组。

1
var arr = Array.from( arguments );

字符串

字符串虽然具有length属性以及indexOf()和concat()方法,但它不同于数组

数字

Javascript只有一种数值类型,包括“整数”和带小数点的十进制数。
数字可以调用Number.prototype中的方法
tofixed()方法可以指定小数部分的显示位数。
toPrecision()方法可以指定有效数位的显示。
还有一种特殊情况
在Javascript中浮点数运算 0.1 + 0.2 === 0.3 //false
从ES6开始我们对证书检测可以使用Number.isInteger()方法

1
2
3
Number.isInteger( 42 ) //true
Number.isInteger( 42.00 ) //true
Number.isInteger( 42.3 ) //false

在ES6中检测一个值是否是安全的整数,可以使用Number.isSageInteger()方法。

特殊数值

Javascript的值中存在null,undefined这样的特殊值。
NaN,表示不是一个数字,无效数值,失败数值,但是还是属于Number类型。同时NaN它和自身不想等 NaN != NaN //true
判断一个值是否是NaN,可以使用 isNaN()方法

值和引用

1
2
3
4
5
6
7
8
9
10
11
12
var a = 2; //a创建了一个2的副本
var b = a; //b创建了一个a的副本
b = 3;

console.log(a); //2
console.log(b); //3

var c = [1,2,3];
var d = c; //创建了一个对c的引用
d.push( 4 );
console.log( c ); //1,2,3,4
console.log( d ); //1,2,3,4

这段代码里面涉及到两个概念

  1. 简单值(基本类型值)Null, undefined, 数值,字符串 简单值通过值复制的方式来赋值/传递
  2. 复合值(对象,数组,函数) 复合值,只能通过引用来赋值,传递

上例中的c和d分别指向同一个复合值[1,2,3]的两个不同引用。c和d仅仅是指向,并非拥有,由于引用指向的值是值本身而非变量,所以一个引用无法更改另一个引用的指向。

1
2
3
4
5
6
7
8
var a = [1,2,3];
var b = a;
console.log( a );
console.log( b ); //创建了一个对a的引用

b = [4,5,6];
console.log( a ); //1,2,3
console.log( b ); //4,5,6

第3章 原生函数(内建函数)

常用的原生函数有

  1. String()
  2. Number()
  3. Boolean()
  4. Array()
  5. Object()
  6. Function()
  7. RegExp()
  8. Date()
  9. Error()
  10. Symbol() ——ES6 中新加入

内部属性[[Class]]

所有 typeof 返回值为”object”的对象都包含一个内部属性[[Class]],一般只能通过Object.prototype.toString()来查看

1
2
console.log(Object.prototype.toString.call([1,2,3])); //object Array
console.log(Object.prototype.toString.call(/regex-literal/i)); //object RegExp

封装对象包装

封装对象扮演者十分重要的角色。由于基本值没有.length和 .toString这样的属性和方法,需要通过封装对象才能访问。不过由于Javascript已经可以自动判断添加封装,我们就可以不需要再封装一遍了。

1
2
3
var a = "abc";
console.log( a.length ); //3
console.log( a.toUpperCase() ); //ABC

拆封

如果想要得到封装对象中的基本类型值,需要使用valueOf()

1
2
3
4
5
6
7
var a = new String( "abc" );
var b = new Number( 42 );
var c = new Boolean( true );

console.log( a.valueOf() ); //abc
console.log( b.valueOf() ); //42
console.log( c.valueOf() ); //true

隐式拆分

1
2
3
4
5
var a = new String( "abc" );
var b = a + ""; //b的值为abc,此处为隐式拆分

console.log( typeof a ); //object
console.log( typeof b ); //string

第4章 强制类型转换

值类型转换

将值从一种类型转换为另一种类型通常称为类型转换。隐式的情况成为强制类型转换。

  1. 显式强制类型转换
    我们能从代码中看出哪些地方是显式类型转化的情况
  2. 隐式强制类型转换
    我们无法直接看出的强制类型转换的情况
    1
    2
    3
    var a = 42;
    var b = a + ""; //隐式强制类型转换
    var c = String( a ); //显式强制类型转换

抽象值操作

ToString

ToString 负责处理非字符串到字符串的强制类型转换

1
2
3
4
5
6
//1.07 连续乘以七个 1000
var a = 1.07 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000;
console.log( a.toString() ); //1.07e+21

var b = [1,2,3];
console.log( b.toString() ); //1,2,3

JSON字符串化
工具函数JSON.stringify()再将JSON对象序列化为字符串时也用到了toString
toJSON()返回一个能够被字符串化的安全的JSON值。

显式强制类型转换

尽量使用显式强制类型转换,使代码可读性更高,更容易理解。
在Javascript社区中,一元运算 + 被普遍认为是显式强制类型转换,但不要经常使用,很容易是代码混乱

1
2
3
4
5
6
7
8
var a = 42;
var b = String( a );

var c = "3.14";
var d = +c; //一元运算显式强制类型转换

console.log( a ); //"42"
console.log( d ); //3.14

隐式强制类型转换

宽松相等和严格相等

宽松相等(==)
严格相等(===)
之间有着重要的区别,特别是在判断条件上
区别: == 允许在相等比较中进行强制类型转换,而 === 不允许

第5章 语法

不要将“语句” 和 “表达式” 混为一谈。
语句是由短语组成,短语我们可以看作为表达式

语句的结果值

每个语句都有结果值,并且该值在目前的状况下无法传递给其他变量

表达式的副作用

多出现在变量提升时,顺序上导致变量值被改变,或是一元算法的前后位置上。

上下文规则

在Javascript语法规则中,有时候同样的语法在不同的情况下会有不同的解释

  1. 大括号
    1) 对象常量
    1
    2
    3
    var a = {
    foo: bar()
    }
    2) 标签
    1
    2
    3
    {
    foo: bar() //foo是bar()的标签 *了解即可*
    }
  2. 代码块
    1
    2
    [] + {} //object 强制转换
    {} + [] //0 强制转换
  3. 对象解构
    在ES6开始,可以使用{…}进行解构赋值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function getData(){
    //..
    return {
    a: 42,
    b: "foo"
    };
    }

    var {a, b} = getData();
    console.log( a, b ); //42 "foo"
    {a, b}就是解构赋值相当于
    1
    2
    3
    var res = getData();
    var a = res.a;
    var b = res.b;
  4. else if 和可选代码块
    Javascript本身没有 else if这种语句,但 else if 极为常见,能省掉一层代码缩进,所以很受青睐。

运算符优先级

书里只简单的介绍了一下 && 运算符优先于 ||,具体的优先级顺序需要去以下地址查询
Operator precedence

短路

对&&和||来说,如果从左边的操作能够得出结果,就可以忽略右边的操作数。我们将这种现象称为——短路 (执行最短路径)

更强的绑定。

自动分号

有时Javascript会自动为代码补上缺失的分毫。

错误

函数参数