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时才会执行。

你可能感兴趣的:(JavaScript 使用问题)