看完这篇文章,你将了解

  • var f = function g() {} 执行后会发生什么
  • 为什么闭包不会被垃圾清除
  • in, instanceof, hasOwnProperty 区别
  • (?=pattern) 匹配什么
  • 日期函数 trick
  • 双向广度优先遍历的优点

前言

今天为止终于把所有题目刷完了,每天花 2 个小时,只做 20 道题,陆陆续续刷了 300 道。

一开始做题我是懵逼的,我以为自己 JS 基础还行,但是一上来就被虐得体无完肤。

然而终究要迈过的坎,强迫自己静下心来,告诉自己只尝试 10 道就行,消灭所有存疑点,然后再做 10 道。这样子一天天下来题目竟越刷越简单了。很多东西真的扫一眼就能知道它玩什么花样。

现在最大的感受,一是刷题确实可以巩固 JS 基础,很多东西就是知之为知之,不知为不知。只想说像这样的题目,不重样的再给我来 1000 道!我还想写 50 篇博客 XD;

二是有一些事一开始看上去很难,但是拆解开来,一天只做一点,难度就大大降低了,回过头来只是纸老虎。

var f = function g() {}

今天被一段代码坑了

var f = function g() {
  return 33
}
typeof g()

结果是 Error。因为 g 是 undefined,g() 自然不合法,必须改为 typeof f() 才不报错

函数有两种定义方式

// 第 1 种
function foo(){...}
// 第 2 种
var foo = function(){...}

而类似于

var foo = function bar() {}

这样的形式,最终 foo 是函数,bar 不是函数,只是函数 foo 的属性 foo.name

闭包

看这篇文章 为什么闭包不会被垃圾回收清除

in, instanceof, hasOwnProperty

  • instanceof:检测一个实例是否为某构造函数,父构造函数生成
  • in:检查一个对象是否有某属性,包括原型链
  • hasOwnProperty:检查一个对象是否有某属性,不包括原型链

(?=pattern) 正向先行断言

  • 代表字符串中的一个位置,紧接该位置之后的字符序列能够匹配pattern
  • 比如:”a regular expression” 这个字符串,要想匹配regular中的re,但不能匹配expression中的re。

可以用 ”re(?=gular)”,该表达式限定了 re 右边的位置,这个位置之后是 gular,但并不消耗 gular 这些字符,将表达式改为 ”re(?=gular).”,将会匹配 reg,元字符.匹配了 g,括号匹配了 e 和 g 之间的位置

  • 又比如:/...(?=.)/.test('abc') 为 false。

因为 ... 表示存在 3 个字符, (?=.) 规定了 3 个字符后必须跟着 1 个字符,所以 'abc' 不符合模式

一年中的第几天

力扣上有一道题目,给出年月日,求该天为同年第几天

一开始我的做法是:

  • 建表,键值对分别为 {月份:累计天数}
  • 取出年月日
  • 根据是否为闰年选月表
  • 按月读表得累计天数,与天数相得到答案
var dayOfYear = function(date) {
    // 建一个月份累计天数哈希表
    let daysHash = {
        'nonleepYear': [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365],
        'leepYear': [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]
    }
    
    // 获取年份和月份和天数
    let ymd = date.split('-')
    let y = +ymd[0]
    let m = +ymd[1]
    let d = +ymd[2]
    
    // 读表知道是否闰年
    let hash = (y % 400 === 0 || (y % 4 === 0 && y % 100 !== 0)) ? daysHash.leepYear : daysHash.nonleepYear
    
    // 读表知道当月累计天数
    let elaspedDays = hash[m-1]
    
    // 累计天数加天数
    elaspedDays += d
    
    return elaspedDays
};

这里有一个判断闰年的技巧

y % 400 === 0 || (y % 100 !== 0 && y % 4 === 0)

然后,发现了一个更简单的做法:

var dayOfYear = function(date) {
    return (new Date(date) - new Date(date.replace(/-\d\d-\d\d/, '-01-01')))/86400000 + 1
};

不得不说 Date 对象简直是 JS 日期处理和时间计算的黑科技

Date 构造函数,可以将字符串转为日期

  • new Date('1999 01 02 03:04:05') // 1999 年 1 月 2 日 3 时 4 分 5 秒
  • new Date('1999 01 02') // 1999 年 1 月 2 日 0 时 0 分 0 秒
  • new Date('01 02 1999') // 同上
  • new Date('01-02-1999') // 同上
  • new Date('1999-01-02') // 同上

记住两个特殊值: 3600000 表示 1 小时,86400000 表示 1 天 (都是 5 个 0)

双向广度优先遍历的优点