JavaScript高级程序设计读书笔记

71 阅读10分钟

Chapter3

  1. typeof操作符的操作数可以是变量, 也可以是字面量typeof name,typeof 10
  2. typeof null -> object 因为特殊值null被认为是一个空对象的引用(null值表示一个空对象指针)
  3. 变量没声明的话, 直接用报错xxx is not defined
  4. var name; // name没有进行初始化 typeof name -> undefined
  5. typeof age -> undefined //age 没有声明
  6. null更多用来初始化对象

类型转换

  1. !!"" -> false
  2. null 和 undefined没有toString()方法, 其他类型都有toString()字符串的toString()方法返回一个字符串的副本
  3. toString(进制数), 默认为10
  4. null和undefined没有toString()方法, undefined.toString()报错Uncaught TypeError: Cannot read property 'toString' of undefined
  5. String()可以转换所有类型数据为字符串; String(null) => "null"; String(undefined) => undefined;
  6. Boolean()转换

    在if(condition)语句中,condition可以是任意表达式, 而且这个表达式的求值结果并不一定是布尔值,ECMAScript会自动调用Boolean() 转换函数将表达式结果转换为布尔值

  7. break直接跳出整个循环; continue跳出本次循环forEach如何跳出循环???"

###类型转换(解释即可)

解释了下面的每一结果的原因,

  1. ['a','b','c'] + ['2', '3','4']
  2. 3<4<2
  3. toString() 和 toValue()

值传递和应用传递

  1. 按值访问和按引用访问
  2. 参数传递:按值传递
  3. 函数的参数传递和变量复制一样
  4. 所谓对象的引用就是栈内存中指向堆内存对象的一个指针值
  5. 参见文章
  6. ES中函数的参数传递都是值传递

类型判断

  1. typeof基本类型检测: undefined, boolean, string, number, function
  2. instanceof 引用类型检测
  1. 所有引用类型值都是Object的实例
  2. instanceof 检测基本类型 return false, 因为基本类型不是变量
  1. typeof /12/ => object 正则表达式也是对象
  2. /12/ instanceof RegExp => true

正则表达式

  1. typeof /12/ => object 正则表达式也是对象
  2. /12/ instanceof RegExp => true

第五章 引用类型

5.1 Object类型

  1. 在最后一个属性后添加,会在IE7以及opera中导致错误
  2. 在使用对象字面量语法时,属性名也可以使用字符串.数值属性名会自动转换为字符串
  3. var person = {} <=> var person = new Object() 在通过对象字面量定义对象时,实际上不会调用Object构造函数
  4. 方括号语法访问对象属性值的有点是: 可以通过变量来访问属性 JavaScript var propertyName = 'name' person[propertyName] //在for循环中根据key值作为变量, 访问对象属性值 // 如果属性名中包含会导致语法错误的字符,或者属性名使用的是关键字或保留字,也可以使用方括号表示法。例如:person["first name"] = "Nicholas"; 由于"first name"中包含一个空格,所以不能使用点表示法来访问它。然而,属性名中是可以包含非字母非数字的,这时候就可以使用方括号表示法来访问它们。通常,除非必须使用变量来访问属性,否则我们建议使用点表示法

5.2 Array类型

  1. 利用length属性也可以方便地在数组末尾添加新项,如下所示:
var colors = ["red", "blue", "green"];
colors[colors.length] = "black";
colors[colors.length] = "brown";
//由于数组最后一项的索引始终是length-1,因此下一个新项的位置就是length。每当在数组末尾添加一项后,其length属性都会自动更新以反应这一变化。
  1. ES5 中检测数组的方法: Array.isArray()
  2. 转换

toString()将数组转换为字符串, [1,2,3,4,5].toString()会调用数组中每一项的toString()方法,之后将其拼接为一个字符串, 中间以逗号分隔

  1. 改写toString()方法和验证上一步骤:
 var person1 = {
   toLocaleString: function() {
       return 'john'
   },
   toString: function() {
       return 'john2'
   }
 }
 var person2 = {
   toLocaleString: function() {
     return 'zhangsan'
   },
   toString: function() {
     return 'zhangsan2'
   }
 }
 var people = [person1, person2]
 console.log(people)
 console.log(people.toString())
 console.log(people.toLocaleString())
  1. 如果数组中的某一项的值是null或者undefined,那么该值在join()、toLocaleString()、toString()和valueOf()方法返回的结果中以空字符串表示
  2. join()
 var colors = ["red", "green", "blue"];
 colors.join('=')  //  "red=green=blue="
 colors //  ["red", "green", "blue"];
 var colors = ["red", "green", "blue", undefined];
 colors.toString() // "red,green,blue,"
  1. sort 1. 默认情况下,sort()方法按升序排列数组项——即最小的值位于最前面,最大的值排在最后面。 为了实现排序,sort()方法会调用每个数组项的toString()转型方法,然后比较得到的字符串,以确定如何排序。 即使数组中的每一项都是数值,sort()方法比较的也是字符串,如下所示

    var values = [0, 1, 5, 10, 15];
    values.sort();
    alert(values);     //0,1,10,15,5
    
2. 自定义排序函数
> 比较函数接收两个参数,
> 如果第一个参数应该位于第二个之前则返回一个负数,
> 如果两个参数相等则返回0,
> 如果第一个参数应该位于第二个之后则返回一个正数。
> 以下就是一个简单的比较函数:

```JavaScript
  function compare(value1, value2){
    if (value1 < value2) { return -1}
    else if (value1 > value2 ) {return 1}
    else {return 0}
  }
  var values = [0, 1, 5, 10, 15];
  values.sort(compare) // values => [0, 1, 5, 10, 15];
  // 注意: 排序之后, 数组的值与之前不同
  // reverse()和sort()方法的返回值是经过排序之后的数组
```

3. 对于数值类型或者其valueOf()方法会返回数值类型的对象类型,可以使用一个更简单的比较函数。这个函数只要用第二个值减第一个值即可(正序)
```JavaScript
function compare(value1, value2){
  return value1 - value2;
}
```

8. 操作方法 1. concat 连接两个数组, arr.concat() => arr保持不变, 返回的是arr的副本 2. slice 不改变原数组 3. splice 改变原数组 9. 位置方法 1. indexOf() 查找使用 === 2. lastIndexOf 同上 3. 使用indexOf()和lastIndexOf()方法查找特定项在数组中的位置非常简单,支持它们的浏览器包括IE9+、Firefox 2+、Safari 3+、Opera 9.5+和Chrome。 10. 归并(求和)操作 1. reduce() 2. reduceRight() 3. 在对对象数组的某一个属性求和的时候注意: 4. 参考链接 5. 这两个方法都接收两个参数:一个在每一项上调用的函数和(可选的)作为归并基础的初始值- <JS高程 5.2.9节 归并方法> 6. // A cleaner way to accomplish this is by providing an initial value: JavaScript var arr = [{x:1}, {x:2}, {x:4}]; arr.reduce(function (prev, cur) { return prev + cur.x; }, 0); // 7

  1. The first time the anonymous function is called, it gets called with (0, {x: 1}) and returns 0 + 1 = 1. 函数第一次调用的时候, 传入(prev, cur)的值是(0, {x: 1})
  2. The next time, it gets called with (1, {x: 2}) and returns `1 + 2 = 3 .
  3. It's then called with (3, {x: 4}), finally returning
  4. 如果不传入最后的0, 函数第一次调用,传入(prev, cur)的值是({x:1}, {x: 2}), 返回值就是"[object Object]2".
  5. 如果有一个操作数是对象、数值或布尔值,则调用它们的toString()方法取得相应的字符串值,然后再应用前面关于字符串的规则。对于undefined和null,则分别调用String()函数并取得字符串"undefined"和"null - <JS高程 3.5.5节 加性操作符>"

5.5 Function类型

  1. 解析器在向执行环境中加载数据时,对函数声明和函数表达式并非一视同仁。解析器会率先读取函数声明,并使其在执行任何代码之前可用(可以访问);至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行
  2. 在代码开始执行之前,解析器就已经通过一个名为函数声明提升(function declaration hoisting)的过程,读取并将函数声明添加到执行环境中。对代码求值时,JavaScript引擎在第一遍会声明函数并将它们放到源代码树的顶部。所以,即使声明函数的代码在调用它的代码后面,JavaScript引擎也能把函数声明提升到顶部
  3. 函数声明
  alert(sum(10,10));
  function sum(num1, num2){     return num1 + num2; }
  1. “unexpected identifier”(意外标识符)错误 => 变量未声明,就直接调用
  2. 因为ECMAScript中的函数名本身就是变量,所以函数也可以作为值来使用。也就是说,不仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回
  3. arguments.callee 表示函数本身
  function factorial(num){
    if (num <=1) { return 1; }
    else return num * arguments.callee(num-1)
  }
  1. arguments.callee.caller 表示函数的调用者
function outer(){
    inner();
  }
  function inner(){
    alert(arguments.callee.caller);
  }
  outer();
  1. 函数的名字仅仅是一个包含指针的变量而已。因此,即使是在不同的环境中执行,全局的sayColor()函数与o.sayColor()指向的仍然是同一个函数
  2. IE、Firefox、Chrome和Safari的所有版本以及Opera 9.6都支持caller属性。当函数在严格模式下运行时,访问arguments.callee会导致错误。ECMAScript 5还定义了arguments.caller属性,但在严格模式下访问它也会导致错误,而在非严格模式下这个属性始终是undefined。定义这个属性是为了分清arguments.caller和函数的caller属性。以上变化都是为了加强这门语言的安全性,这样第三方代码就不能在相同的环境里窥视其他代码了。严格模式还有一个限制:不能为函数的caller属性赋值,否则会导致错误
  3. 函数的length表示函数希望接受的参数个数
  4. call 与 apply扩充函数作用域的最大好处: 对象不需要与方法有任何耦合关系
  5. call, apply, bind
  6. new Number('10') 与 Number('25')不一样. 后者是类型转换函数, 参见第三章类型转换
  1. typeof new Number('10') => 'object'
  2. typeof Number('10') => 'number'

5.6.3 String类型

  1. 位置

    1. charAt
    2. charCodeAt 获得字符编码
    3. 可以使用方括号加数字索引来访问字符串中的特定字符, 'abcd'[1], IE8及以上支持
  2. 操作

    1. concat => +
    2. slice() , 参数[开始位置, 结束位置)
    3. substring(), 参数[开始位置, 结束位置) 在对字符串操作时候, 与上述相同
    4. substr(), 参数[开始位置, 返回字符串个数]
    5. slice()、substr()和substring() 指定一个参数时候(非负数), 返回值都是从指定位置到字符串最后一个字符(包含最后一个)的子字符串, 传递一个参数是负数时, var stringValue = "hello world"
    1. stringValue.substr(-3) => stringValue.substr(11-3) => stringValue.substr(8) IE的JavaScript实现在处理向substr()方法传递负值的情况时存在问题,它会返回原始的字符串。IE9修复了这个问题。
    2. stringValue.slice(-3) => stringValue.slice(11-3) => stringValue.slice(8)
    3. stringValue.substring(-3) => stringValue.substring(0) => 返回值就是整个字符串了
    1. 传递第二个参数是负数时, var stringValue = "hello world"

    1. stringValue.slice(3, -4) => slice(3,7)
    2. stringValue.substring(3, -4) => stringValue.substring(3, 0) => stringValue.substring(0,3) substring()方法会把第二个参数转换为0,使调用变成了substring(3,0),而由于这个方法会将较小的数作为开始位置,将较大的数作为结束位置,因此最终相当于调用了substring(0,3)
    3. substr()也会将第二个参数转换为0,这也就意味着返回包含零个字符的字符串,也就是一个空字符串. 因为substr第二个参数代表的是返回字符串的个数,既然第二参数变为0了, 因此也就返回0个字符, 也就是空字符串
    1. 利用indexOf 查询字符串中某元素的所有位置
    var stringValue = "Lorem ipsum dolor sit amet, consectetur adipisicing elit";
    var positions = new Array();
    var pos = stringValue.indexOf("e");
    while(pos > -1){
        positions.push(pos);
        pos = stringValue.indexOf("e", pos + 1);
    }
    alert(positions);    //"3,24,32,35,52"
    
    1. trim()去除字符串两端空格实现:`IE9+、Firefox 3.5+、Safari 5+、Opera 10.5+和Chrome支持
    String.prototype.trim = function() {
      return this.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
    }
    

5.7 单体内置对象

  1. Math 1. Math.floor() 2. Math.ceil() 3. Math.round() 4. Math.min.apply(Math, 数组) 5. Math.max.apply(Math, 数组) > 这个技巧的关键是把Math对象作为apply()的第一个参数,从而正确地设置this值。然后,可以将任何数组作为第二个参数 6. Math.max(11,22,33,44,55). Math.max()的参数不能是数组,因此如果比较数组的话, 需要把数组作为apply的参数传入. 7. Math.random() 返回值: [0, 1) 与Math.floor配合可以得到[2, 10] 或 其它区间
```JavaScript
function selectFrom(lowerValue, upperValue) {
  var choices = upperValue - lowerValue + 1;
  return Math.floor(Math.random() * choices + lowerValue);
}
var num = selectFrom(2, 10);
alert(num);   // 介于2和10之间(包括2和10)的一个数值
var colors = ["red", "green", "blue", "yellow", "black", "purple", "brown"];
var color = colors[selectFrom(0, colors.length-1)];
alert(color);  // 可能是数组中包含的任何一个字符串
```

第23章 离线应用与客户端存储

  1. 23.3 数据存储
  2. Cookie 1. cookie的key 和value都必须是URL编码的??? 2. cookie与session如何进行配合 3. 怎么验证该多个请求是同一个回话中发出的呢?和token进行比较呢??

  1. 变量赋值

这说明JavaScript实际上只有一个全局作用域。任何变量(函数也视为变量),如果没有在当前函数作用域中找到,就会继续往上查找,最后如果在全局作用域中也没有找到,则报ReferenceError错误。

'use strict';
var old_alert = window.alert;
window.alert = function(){ }
  1. 变量提升: 变量提升时,函数声明的变量名字和值都会提升,而函数表达式只提升名字。
demo();
test();
function demo(){
console.log('demo');
}
var test = function(){
   console.log('test');
};
/*结果: VM2970:3 Uncaught TypeError: test is not a function(…)*/