js怪癖-undefined和null及引申

undefinednull

  1. undefined 是JavaScript语言本身分配的,如果一个变量还没有被初始化,那么他的值就是 undefined
  2. null 是被开发者用来明确指出某个值是缺失的,例如,对于JSON.stringify()
  3. 如果需要知道变量 x 是否有值,通常情况下,你需要同时,校验 undefinednull

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    if (x != null) {
    // 有值的操作 (false, -0, +0, NaN)都被认为是有值
    } else {
    // 没有值时,执行的操作
    }
    ```
    相等于
    ```javascript
    if (v !== undefined && v!== null) {
    // 有值
    } else {
    // 没值
    }

    另外一种逻辑

    1
    2
    3
    4
    5
    if (x == null) {
    // 没值
    } else {
    // 有值
    }

隐式类型转换

0. 提要

  1. 自动转换为布尔值通常不会引起问题,而且往往很有用

1. 隐式转换为布尔: “ truthy ” 和 “ falsy ”

  1. 当JavaScript需要一个布尔值时(if 语句),会触发隐式转换为布尔值,Boolean()
  2. 算法
    1. 下面这些值将被转换为false
      1. undefined, null
      2. Boolea: false
      3. Number: -0, +0, NaN
      4. String: ‘’
    2. 其他值都被认为是 true

2. 字符串的隐式转换

  1. 加运算符 +,当其中一个操作数是字符串的时候,就会执行拼接字符串的操作

3. 对象的隐式转换

  1. 只有在 JavaScript 表达式或语句需要用到数字或字符串时,对象才被隐式转换。
    1. 需要转换为数字时
      1. 调用 valueOf(),如果结果是原始值,则将其转换为一个数字
      2. 否则,调用 toString()方法,如果结果时原始值,则将其转换为一个数字
      3. 否则,抛出一个类型错误
    2. 需要转换为字符串的时候
      1. 上面的算法,第一步与第二步调换。

参数的处理

  1. 可以传递任意的参数
    1. 缺失参数的值是undefined
    2. 多出来的参数则被直接忽略掉
    3. ES6: 参数默认值
    4. ES6: 不定参数,必须在最后一个
  2. 所有传递的参数都储存在一个特别的,类数组对象 arguments中
  3. 判断参数是否传递了?

    1. 一个不严谨的方法

      1
      2
      3
      4
      5
      6
      7
      function hasParameter (param) {
      if (param) {
      return 'yse'
      } else {
      return 'no'
      }
      }

      这个情况,对于虚拟值(falsy)的运用是非法的,比如false、0以及空字符串都会被解析为缺失参数

    2. 仅仅判断undefined
      1
      2
      3
      4
      5
      6
      7
      function hasParameter (param) {
      if (typeof param !== undefined) {
      return 'yes'
      } else {
      return 'no'
      }
      }
  4. 参数默认值ES5实现

    1. 简单版,传递虚拟值(falsy): false、0 、空字符等同于没传递,将会使用默认值

      1
      2
      3
      4
      5
      function plus (x, y) {
      x = x || 1
      y = y || 1
      return x * y
      }
    2. 严谨版,typeof x === undefined

  5. 强制执行一定数量的参数

    1. 通过arguments.length验证
      1
      2
      3
      4
      5
      6
      7
      8
      function add (x, y) {
      if (arguments.length > 2) {
      throw new Error('Need at most 2 parameter')
      } else if ( arguments.length < 2) {
      throw new Error('Need at least 2 parameter')
      }
      return x + y
      }
  6. arguments 不是 array

    1. arguments 并不是 array,它只是像array,暂且知道两点方法像array
      1. 获取第i个参数,argument[i]
      2. argument.length
    2. 转换函数
      1
      2
      3
      function fromArray (arrayLikeValue) {
      return Array.prototype.slice.call(arrayLikeValue)
      }
  7. 函数参数的个数

    1. 函数直接传入参数是最常见的
    2. 不过如果参数个数太多。程序的可读性就下降了,调用起来也麻烦 – 比如记不清每个位置的参数含义,记不清顺序等。
    3. 通常函数参数的个数不应该超过4个。
    4. 如果有更多的配置需求呢?把多个参数合成为一组配置,以单一参数传递,JS中就是对象object