《JavaScript语言精粹》读书笔记

二刷《JavaScript语言精粹》,做些笔记在这里。
看过有些对这本书有些非议的说法,我想主要是这本书讨论的是 ES5 的原因吧,毕竟第一版出版距现在已经有7年时间之久了。
而如今我们更多时候是在讨论 ES6,MVVM 框架和虚拟 DOM,构建工具等等。
但有一点可以肯定,目前我们还是避不开 ES5 的。


第2章 语法

  • NaN 不等于任何值,包括它自己。
    我们使用 isNaN(number) 来检测 NaN。

  • 当 var 语句用在函数内部时,它定义这个函数的私有变量。

  • ES5 中代码块不会创建新的作用域,因此变量应该被定义在函数的头部,而不是代码块中。

  • for in 会枚举一个对象的所有属性名或键名,通常配合 object.hasOwnProperty() 来检查属性名是该对象的成员,还是来自原型链。

for(vari in obj){
  if(obj.hasOwnProperty(vari)){
    ...
  }
}
  • return 语句会导致函数中提前返回。也可以指定要被返回的值。
    如果没有指定返回表达式,那么返回值是 undefined。

  • typeof 运算符产生的值有number, string, boolean, undefined, function 和 object
    如果运算数是一个数组或 null,那么结果是 object,这其实是不对的。


第3章 对象

  • JavaScript 的简单数据类型包括 string,number,boolean,undefined,null 。其它所有的值都别看作是对象。
    string,number 和 boolean 貌似对象,因为它们拥有方法,但它们的值可以改变。

  • 对象是属性的容器。

  • 如果尝试检索一个不存在的属性,将返回 undefined。

  • 对象的值可以通过赋值语句来更新。如果属性名存在,那么属性值就会被替换:
    obj.silence = "hush hush"
    如果对象之前没有这个属性名,那么该属性就被扩充到对象中。

  • 当我们对某个对象改动时,不会触及该对象的原型。

  • 如果我们尝试获取某个属性值,但该对象没有此属性,那么 JavaScript 会试着从原型对象中获取属性值。
    如果原型对象也没有改属性值,那么再从它的原型中寻找以此类推,直到该过程最后到达终点 Object.prototype。

  • 原型关系是动态的。如果我们添加一个属性到原型中,该属性会立即对所有基于该原型创建的对象可见。


第4章 函数

  • 函数用于指定对象的行为。
    函数可以保存在变量,对象和数组中。
    函数可以被当做参数传递给其它函数,函数也可以再返回函数。
    而且,因为函数是对象,所以函数可以拥有方法。

  • 函数对象可以通过函数字面量形式来创建:

var foo = function(a, b){
  return a + b;
}

函数分4个部分:
第1部分是关键字 function。
第2部分是函数名,它是可以被省略的。函数可以用它的名字来递归调用自己。如果没有给函数命名,比如上面例子,那么这个函数被称为"匿名函数"。
第3部分是参数。第4部分是函数主体。

  • 函数也可以被定义在其它函数中。
    一个函数内部的函数除了可以访问自己的参数和变量,同时也能自由访问把他嵌套在其中的父函数的参数和变量。
    通过函数字面量创建的函数对象包含一个连接到外部上下文的链接。这被称为闭包。

  • 如果实际参数值过多,超出的参数值会被忽略。
    如果实际参数值过少,缺失的值会被替换为 undefined
    对参数值不会进行类型检查,任何类型的值都可以传递给参数。

  • 除了声明时定义的形式参数,每函数还接受两个附加的参数:thisarguments
    参数 this 在面向对象中非常重要,它的值取决于调用模式。总共有4中调用模式:方法调用模式,函数调用模式,构造器调用模式和 apply 调用模式。

    • 方法调用模式:
      当一个函数被保存为对象的一个属性时,我们称它为一个方法。
      当一个方法被调用时,this 被绑定到该对象。
      var obj = {
        val: 0,
        increase: function(){
          this.val++
        }
      }
      obj.increase();  //方法调用
      
      方法可以使用 this 访问自己所属的对象,从中取值或对对象进行修改。
      通过 this 可取得它们所属对象的上下文的方法称为公共方法。
    • 函数调用模式:
      当一个函数并非一个对象的属性时,即是函数调用。
      var sum = add(3, 4); //函数调用
      此时,this 被绑定到全局对象。
    • 构造器调用模式:
    //  创建一个名为 Person 的构造器函数。
    var Person = function(param){
      this.name = param;
      getName: function(){
        return this.name;
      }
    }
    var pitt = new Person('Brade Piit');  //  构造一个实例
    console.log(pitt.getName());  //  打印 "Brade Pitt"
    
一个函数创建目的就是希望结合new 前缀来调用,那么它就被称为构造器函数。
  * Apply(Call / Bind) 调用模式
  apply 方法允许我们构建一个参数数组传递给函数。允许我们选择 this 值。
  apply 方法接受两个参数,第一个是要绑定给 this 的值,第二个就是一个参数数组。

var arr = [3, 4];
var sum = add.apply(null, arr);


* 定义在函数中的参数和变量在函数外部是不可见的。而在函数内部任何地方都可见。

* 最好的做法是在函数体内顶部定义所有需要的变量。

* 作用域的好处是内部函数可以访问外部函数的参数和变量(this 和 arguments 除外)。

***

### 第8章 方法

* Array
* `array.concat(item)`
concat 方法产生一个新数组,它包含一份 array 的前复制并把若干个参数 item 附加在其后。

var a = [1, 2, 3];
var b = [4, 5, 6];
var c = a.concat(b, 7);
// c 变成 [1, 2, 3, 4, 5, 6, 7]

* `array.join(separator)`
join 方法把一个 array 构造成一个 string,它把 array 中的每个元素构造成一个字符串接着用 separator 分隔符把它们连接在一起。

var arr = ['a', 'b', 'c'];
var str = arr.join(',');
// str 为 "a,b,c"

  * `array.push(item)`
push 方法把一个或多个参数 item 附加到一个数组的尾部。

var a = [1, 2, 3];
var b = 'x';
var c = a.push(b);
// c 为 [1, 2, 3, x]

  * `array.pop()`
pop 方法与 push 正相反,它将一个数组中的最后一个元素移除。
  * `array.unshift(item)`
unshift 方法和 push 方法类似,将参数填充的数组中,不同的是,它将参数填充到数组头部。

var a = [1, 2, 3];
var b = a.unshift(0);
// b 为 [0, 1, 2, 3]

  * `array.shift()`
shift 方法与 unshift 正相反,它将数组头部的元素移除。
  * `array.slice(start, end)`
slice 方法对 array 中的一段做浅复制。
var a = [1, 2, 3, 4];
var b = a.slice(2, 1);
//  b 为 [3]
  * `array.splice(start, deleteCount, item)`
splice 方法从 array 中移除一个或多个元素,并用新的 item 替换它们。
var a = [1, 2, 3, 4, 5];
var b = a.splice(1, 3, 'a');
// b 为 [1, a, 5]
* Number
  * `number.toFixed(fractionDigital)`
    toFixed 方法把数字转换成一个十进制数字。可选参数 fractionDigital 控制其小数点后的位数。
    ```
    var PI = 3.1415926
    PI.toFixed(2)  //  3.14
    PI.toFixed(10)  //  3.1415926000
    ```
  * `number.toPrecision(precision)`   
    toPrecision 方法把数字转换成一个十进制数字。可选参数与 toFixed 方法略有不同,它控制的是整个数字的有效位数。
    ```
    PI.toPrecision(2);  //  3.1
    PI.toPrecision(10);  //  3.14159265300
    ```
  * `number.toString()`
    toString 方法把数字转换成一个字符串。
* RegExp
  * `regexp.test(string)`
    test 方法匹配 string,则返回 true。
    不要对整个方法使用全局匹配(不使用 g 标识)。
* String
  * `string.charAt(position)`
    charAt 方法返回字符串中 position 位置的字符。
    如果 position 小于0或大于字符串长度,则返回空字符串。
    ```
    var str = 'Curry'
    var initial = str.charAt(0)  //  'C'
    ```
* `string.indexOf(searchString, position)`
    indexOf 方法用来检测字符串中是否含有搜索的字符串 searchString,如果是则返回第一个匹配字符的位置,如果否则返回-1。
    可选参数 position 可设置从 string 的某个位置开始查找。
    ```
    var name = 'Jack Sparrow'
    name.indexOf('ac')  //  1
    name.indexOf('pa', 5)  //  1
    ```
* `string.lastIndexOf(searchString, postion)`
    与 indexOf 方法类似,只是从字符串的尾部开始查找。
* `string.slice(start, end)`
    slice 方法浅复制 string 的一部分来构造一个新的字符串。
* `string.split(separator, limit)`
    split 方法把字符串分割成片段来创建一个数组。
    可选参数 limit 控制最多分割的片段数量。
    如果 separator 是空字符,则返回单字符数组。
    ```
    var digi = `1234567890`
    var arr = digi.split('', 5)  //  ['1', '2', '3', '4', '567890']
    ```
* `string.toLowerCase()`
    toLowerCase 返回一个新的字符串。string 中所有字符被转换成小写字符。
* `string.toUpperCase()`
    toUpperCase 返回一个新的字符串。string 中所有字符被转换成大写字符。




*[完]*

你可能感兴趣的:(《JavaScript语言精粹》读书笔记)