你不知道的Javascript(中卷)笔记

类型

typeof 判断类型,返回的是类型的字符串值
特殊:

1
2
3
4
5
typeof null === 'object'
typeof function a() {} === 'function'
var a
typeof a // 'undefined'
typeof b // 'undefined' // 即使b未声明,也会返回undefined

函数是对象的一个子集,也有属性,比方说a.length,是声明的参数个数。
变量没有类型,但他们的值持有类型。

如果字符串键值能被强制类型转换为十进制数字的话,它就会被当做数字索引来处理。

1
2
3
var a = [];
a['13'] = 42;
a,length; //14

字符串是类数组,具有 length 属性以及 indexof() 和 concat() 方法。
字符串是不可变的,也就是字符串的成员函数不会改变其原始值,数组是可变的。有的操作可以先”借用”数组的方法。
undefined 只有一个值,即 undefined,null 类型也只有一个值,即 Null。它们的名称既是类型也是值。

1
2
null:指空值;曾经赋过值,但目前没有值;是一个特殊的关键字,不是标识符
undefined:指没有值,从未赋值;是一个标识符,可以被当做变量来使用和赋值

NaN 指”不是一个数字”,理解为”无效数值”、”失败数值”、”坏数值”。他和自身不相等,是唯一一个非自反的值,即 NaN != NaN 为true。
怎么判断一个值是 NaN 呢? ES6 有工具函数Number.isNaN()可以判断。

原生函数

所有 typeof 返回值为”object” 的对象都包含一个内部属性[[Class]],这个属性无法直接访问。一般通过Object.prototype.toString(...)来查看。
基本类型是没有.length 和 .toString() 这样的属性和方法,需要通过封装类型才能访问,此时 Javascript 会自动为基本类型值包装一个封装对象。

1
2
3
4
var a = new Boolean(false);
if(!a) {
console.log('Oops'); // 执行不到这里
}

获取一个封装对象中的基本类型值,可以使用 valueOf() 函数。

强制类型转换

抽象值操作

  • ToString
    负责处理非字符串到字符串的强制类型转换
    基本类型规则:null 转换为 “null”,undefined 转换为 “undefined”,true 转换为 “true”。
    普通对象来说,除非自定义,否则 toString() 会返回内部属性[[Class]]的值,如”[[object Object]]”。
    数组的 toString() 经过了重新定义,将所有单元字符串化后再用”,”进行连接。
  • ToNumber
    true 转换为1,false 转换为0,null 转换为0,undefined 转换为NaN。
    对象(包括数组)会首先被转换为相应的基本类型值,如果返回的是非数字的基本类型值,再通过规则将其转换为数字。
    将值转换为基本数据类型,ES规范会检查是否有 valueOf() 方法,如果有并且返回基本类型值,则使用该值进行强制类型转换,如果没有就使用toString()的返回值进行强制类型转换。
  • ToBoolean
    以下这些是假值:undefined、null、false、+0、-0 和 NaN、””。假值类型的布尔强制类型转换结果为 false。
    假值对象:他们都是封装了假值类型的对象。
    1
    2
    3
    var a = new Boolean(false); // true
    var b = new Number(0); // true
    var c = new String(""); // true

显式强制类型转换

  • 字符串和数字的显示转换

字符串和数字之间的转换是通过 String(…) 和 Number(…) 这两个内建函数(原生构造函数)来实现的,请注意它们前面没有 new 关键字,并不创建封装对象。
日期转换为数字

隐式强制类型转换

  • 字符串和数字的隐士强制类型转换

    • 运算符能用于数字加法,也能用于字符串拼接,那么怎么判断执行哪个操作呢?
      1
      2
      3
      4
      5
      6
      7
      8
      1 + '1' // 11
      1 + true // 2
      1 + false // 1
      1 + undefined // NaN
      'a' + true // atrue
      var a = [1, 2]
      var b = [3, 4]
      a+b // "1,23,4"

    如果 + 的其中一个操作数是字符串(或者通过以下步骤可以得到字符串)则执行字符串拼接,否则执行数字加法
    步骤:如果其中一个操作数是对象(包括数组),对其首先进行 ToPrimitive 抽象操作,该抽象操作再调用[[DefaultValue]],以数字作为上下文。

  • 布尔值和数字的隐士强制类型转换

宽松相等和严格相等

常见误区是:“==检查值是否相等,===检查值和类型是否相等”。
正确解释是:“==允许在相等比较中进行强制类型转换,而===不允许”

  • 字符串和数字之间的相等比较
    x == y:x 是数字,y 是字符串,则将 字符串y 转换为数字(ToNumber(y))进行判断。
  • 其他类型和布尔值的相等比较
    x == y: x 是布尔值,则将布尔值 x 转换为数字(ToNumber(x))进行判断。
    1
    2
    3
    var x = true;
    var y = "42";
    x == y // false

首先将 x 转换为数字1,则接下来进行 1 == “42”的比较,”42”转换为数字42,最后变成 1== 42,则为 false。
建议:无论什么情况下都不要使用 == true 和 == false

  • null 和 undefined 的相等比较
    x == y:x 为 null, y为 undefined,则结果为 true
    1
    2
    3
    4
    var a = dosomething();
    if(a == null) {
    // ...
    }

条件判断仅在 dosomething() 返回 null 和 undefined 时才成立,除此之外都不成立,包括0、 false 和 “” 这样的假值。

  • 对象和非对象直接的相等比较
    x == y: x 是字符串或数字,y 是对象,则将 y 转换为 ToPrimitive(y) 进行比较。

  • 安全运用隐士强制类型转换
    如果两边值中有 true 或 false,千万不要使用 ==。
    如果两边值有[]、””或0,千万不要使用==。