看完这篇文章,你将了解

  • 数字与字符串运算规律
  • 函数提升
  • JS 位运算符(^ 是什么运算)
  • hasOwnProperty 方法
  • Date.prototype.setDate 方法
  • 二分查找模板
  • 如何生成不重复的随机序列

数字与字符串运算规律

最近遇到多种 String + Number, Number - String 的问题

总结一下,无非分为两种情形

  • 加法

    1 + "2"  // "12"
    "1" + 2  // "12"
    1 + "a" // "1a"
  • 减法

    2 - "1" // 1
    "2" - 1 // 1
    2 - "a" // NaN
    "a" - 2 // NaN
    "a" - "b" // NaN

可见,加法转为字符串,减法转为数字

函数提升

之前一直没有分清变量提升中函数的提升机制,今天通过一段代码终于懂了

var a = 10;
function a(){}
console.log(typeof a)

我以为输出 "function",结果是 "number"

原来变量提升还分函数提升,而函数提升优先级高于变量提升

上面代码等价于

function a(){}
var a;
a = 10;
console.log(typeof a)

所以 a 值被数字覆盖

JS 位运算符

OperatorDescriptionExampleResult
&AND0101 & 00010001
lOR0101 l 00010101
~NOT~01011010
^XOR0101 ^ 00010100

^ 运算符是 JS 与其他语言相比比较特殊的符号,它不是幂,而是异或,异或就是找不同

hasOwnProperty()

用来判断某个对象是否含有指定的属性,和 in 运算符不同,该方法会忽略掉那些从原型链上继承的属性。

Date.prototype.setDate()

setDate() 方法根据本地时间来指定一个天数,一般表示该月第几天

  • setDate 如果指定数字为负,他会从上个月最后一天开始推算目标日期
  • setDate 如果指定数字为 0,它会设定日期为上个月最后一天
  • setDate 如果指定数字超过范围,它会从当前月份第 1 天开始推算目标日期

其实只要记住一点:0 代表上个月最后一天,以该天为原点列数轴即可

细节

  • RegExp 正则参数可以不加双斜杠
  • 数组转字符串相当于 join(“,''),对象转字符串则返回 “[object Object]”,记这一点是因为这个例子

    var str1=new RegExp("e");
    document.write(str1.exec("hello"));

这里 str1.exec() 的返回值不是对象,而是数组

  • 最近经常看到 escape 方法,它的作用是将字符串转为十六进制格式(UTF16),与 unescape 配对
  • 正则表达式里 i, m 表示忽略大小写,匹配新行
  • setTimeout 不是全局函数是因为 es 标准没有此函数,浏览器各自实现

判断一个数是否为完全平方数的方法

  • 暴力循环

    let i = 0
    while(i * i < num) i++
    return i * i === num
  • 数学定理

    // 1 + 3 + 5 + ... + (2n - 1) = n ^ 2
    let i = 1
    while(num > 0) {
        num -= i
        i += 2
    }
    return num === 0
  • 二分查找(见下)

二分查找

这里有一份 JS 二分查找的模板

/**
 * @param {number} num
 * @return {boolean}
 */
var isPerfectSquare = function(num) {
    // 以 0 为起点, num 为终点二分查找
    
    let left = 0
    let right = num
    
    while(left <= right) {
        let mid = Math.floor((left + right) / 2)
        if(mid * mid < num) left = mid + 1
        if(mid * mid > num) right = mid - 1
        if(mid * mid === num) return true
    }
    
    return false
};

注意两点:left 与 right 的循环条件是小于等于;mid 是向下取整

生成不重复的随机序列

假设要对一个对象数组随机排序

let randSeq = Object.keys(arr).sort((a, b) => .5 - Math.random())