JavaScript 使用问题

  1. 判断对象为空
JSON.stringify(object) === '{}'
Object.keys(object).length === 0
  1. 在回调函数中this为undefined
    setTimeout(function() { this }, 1000)的回调函数中this为undefined。
  • 可使用箭头函数作为回调函数
    setTimeout(() => { this }, 1000)
  • 可让this先赋值给一个变量
var scope = this
setTimeout(function() { scope }, 1000)
  1. 判断对象的值时一定要先做非空判断
    否则运行会在此处停止,也不报错。
let a = {a: 1, b: 3}
if (a && a.c) {
    console.log("a.c存在")
} else {
    console.log("a.c不存在")
}

此时会走else分支。
若使用下面代码

let a = {a: 1, b: 3}
if (a && a.c.d) {
    console.log("a.c.d存在")
} else {
    console.log("a.c.d不存在")
}

此时当代码运行到a.c.d处就会停止,不再执行后面代码。
正确写法为

let a = {a: 1, b: 3}
if (a && a.c && a.c.d) {
    console.log("a.c.d存在")
} else {
    console.log("a.c.d不存在")
}

也可以写成(a && a.c && a.c.d) ? a.c.d : ""
也可以使用链运算符(a?.c?.d) ? a.c.d : ""

  1. 导入excel转换为对象
importXLSX: function(callback) {
        // 创建input file
        let file = document.createElement('input')
        file.setAttribute('id','filefilefilefilefilefilefile');
        file.setAttribute('type','file');
        file.setAttribute('accept','.xlsx');
        file.setAttribute("style",'visibility:hidden');
        document.body.appendChild(file);
        // 监听选择事件
        file.addEventListener('change', val => {
            let xlsx = val.target.files[0]//取选择的第一个文件
            if (xlsx) {
                //将xlsx转换为对象
                let reader = new FileReader()
                reader.onload = function(e) {
                    let cfb = XLSX.read(e.target.result, {type: 'binary'})
                    let sheetName = cfb.SheetNames[0]//每个excel有多个工作表 这里取第一个
                    let oJS = XLSX.utils.sheet_to_json(cfb.Sheets[sheetName])
                    callback(oJS)
                };
                reader.readAsBinaryString(xlsx)
            }
        })
        //触发点击事件弹出文件选择
        file.click();
    },

使用上面方法获取的对象,你会发现时间会变成一个数字,可使用下面方法来转换成正常时间。

formatExcelDate(num, format="yyyy-MM-dd HH:mm:ss") {
        if (isNaN(Number(num))) {
            return num
        }       
        const time = new Date((num - 1) * 24 * 3600000 + 1)
        time.setYear(time.getFullYear() - 70)
        time.setHours(time.getHours() - 8)
        const year = time.getFullYear() + ''
        const month = time.getMonth() + 1 + ''
        const day = time.getDate() + ''
        const hours = time.getHours() + ''
        const hours1 = time.getHours()%12 + ''
        const minutes = time.getMinutes() + ''
        const seconds = time.getSeconds() + ''
        const option = {
            "Y+": year,
            "y+": year,
            "M+": month,
            "d+": day,
            "H+": hours,
            "h+": hours1,
            "m+": minutes,
            "s+": seconds,
            // 有其他格式化字符需求可以继续添加,必须转化成字符串
        }
        for (let k in option) {
            let ret = new RegExp("(" + k + ")").exec(format);
            if (ret) {
                if (ret[1].length > option[k].length) {
                    //如果format每项的长度大于日期对应的数值 即yyyyy和2021,此时要上2021前补0 
                    format = format.replace(ret[1], option[k].padStart(ret[1].length, "0"))
                } else {
                    //若小于 即yy与2021,此时只取后面的21
                    format = format.replace(ret[1], option[k].slice(option[k].length - ret[1].length))
                }
            }
        }
        return format
    }, 
  1. 将对象导出为excel
exportXLSX: function(array, titles, fileName = "list.xlsx") {
        if (!array || array.length == 0) return
        let datas = []
        // 将 {a: "测试", b: "张三"} 变成 {"标题": "测试", "姓名": "张三"}
        for (let item of array) {
            let dict = {}
            for (let t in titles) {
                if (t.indexOf("$") != -1) {
                    //t中有$ 向最里层取值
                    let itemValue = item
                    let keys = t.split("$")
                    for (let s of keys) {
                        itemValue = itemValue[s]
                    }
                    let titleValue = titles[t]
                    dict[titleValue] = itemValue
                } else {
                    //t中没有$ 根据titleValue的类型取值
                    let last = array.indexOf(item) == (array.length - 1)//是否为最后一项
                    let titleValue = titles[t]
                    let itemValue = item[t]
                    while (titleValue) {
                        if (typeof(titleValue) == "string") {
                            //titleValue为字符串时 直接赋值
                            dict[titleValue] = itemValue;
                            if (last) {
                                //当最后一个元素时 将titles中的value变成中文字符串 以供json_to_sheet使用 
                                //即 {c: {d: "年龄" }}, 变为 {c: "年龄"}
                                //若在第一个元素时修改 会影响后续元素的判断 所以在最后一个元素时修改
                                titles[t] = titleValue
                            }
                            break
                        } else if (typeof(titleValue) == "object") {
                            //支持嵌套判断 此处只判断是否为对象 请不要传正则、数组等 它们也是对象
                            let nextTitleKey = Object.keys(titleValue)[0]
                            let nextTitleValue = Object.values(titleValue)[0]
                            itemValue = itemValue[nextTitleKey]
                            titleValue = nextTitleValue
                        } else {
                            break
                        }
                    }
                }
            }
            datas.push(dict)
        }
        // 创建一个工作薄对象
        let wb = XLSX.utils.book_new()
        // 将数据转换为工作表 表头为titles中的value
        let ws = XLSX.utils.json_to_sheet(datas, { header: Object.values(titles) })
        // 工作薄中添加一个表sheet 表的内容为ws
        let sheetName = "sheet"
        wb.SheetNames.push(sheetName)
        wb.Sheets[sheetName] = ws
        //写入的样式
        let wopts = { 
            bookType: 'xlsx', bookSST: false, type: 'binary', cellStyles: true, showGridLines: false ,
        } 
        //创建二进制对象写入转换好的字节流
        let wbout = XLSX.write(wb, wopts)
        let blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' })
        // 创建对象超链接
        var href = URL.createObjectURL(blob); 
        // 创建a标签 模拟点击事件下载文件
        let a = document.createElement('a')
        a.setAttribute('id','downloaddownloaddownloaddownload')
        a.setAttribute('href', href)
        a.setAttribute('download', fileName)
        a.setAttribute("style", 'visibility:hidden')
        document.body.appendChild(a);
        a.click()
        setTimeout(function() {
            //释放字节流
            URL.revokeObjectURL(blob);
        }, 100);
    }

// 字符串转字符流
function s2ab(s) { 
    var buf = new ArrayBuffer(s.length);
    var view = new Uint8Array(buf);
    for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
    return buf;
}

titles支持如下

titles: {
        a: "标题",
        b: "姓名",
        c: {
            d: "年龄"
        },
        e: {
            f: {
                g: "地址"
            }
        },
        "h$i$j": "特殊1",
        "h$i$k": "特殊2",
        l: {
            m: "特殊3",//不支持导出下面的n 只会导出m
            n: "特殊4"//不支持 请使用 "l$n": "特殊4"
        }
    }
  1. 在字符串中插入变量
let a = aaa
let b = "111" + a + "222"
let c = `111${a}222`

必须使用数字1左边的`,${}才有效。

  1. 三相运算符
    通常会使用let a = b ? b : "",当b为不为空时,a赋值为b,否则a赋值为""。
    可写成let a = b || "",也能实现对应功能,这个写法会在 b 为false 0 null undefined时执行;
    可写成let a = b ?? "", 与 || 功能相同,但只有b为null undefined时才会执行。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容