蝴蝶书看了,也知道充满了毒瘤和糟粕,但该用还是得用。
实际写了几天,小技巧记录下来。都是在py里有直接答案,不会遇到的问题,没想到js里这么费事。
还是要多读《ES6标准入门》
1判断object是[]还是{}
主要是转xml时是否正确,所以得判断这个。没想到这么麻烦。
抄这个答案,
基本符合需要
if((Array.isArray(变量) && 变量.length === 0) || (Object.prototype.isPrototypeOf(变量) && Object.keys(变量).length === 0)){ alert('该方法判断了{}花括号这种情况!');}
2 deepcopy
obj = JSON.parse(JSON.stringify(o))
3 根据object属性值判断object在array中的index
var array1 = [5, 12, 8, 130, 44];function findFirstLargeNumber(element) { return element > 13;}console.log(array1.findIndex(findFirstLargeNumber));// expected output: 3
4 boolean值逻辑取反用! 而不是~
js里~是位取反。反正作为逻辑判断效果不对,记住和py不同就行了。
5 字符串format
node这样写
import util from "util";const str_out = util.format('%s/%s.html',path, name)
es6里这样写,反引号模板
const str_out = `${path}/${name}.html`;
node相当于py3.6之前的,写法,而es6相当于py 3.6之后:
str_out = f'{path}/{name}.html'
还是py 最简洁 -_-!
反正现在的流行语言和框架,都是互相抄的。感觉区别不是很大。
让我决定语言取舍的,还是擅长的领域,谁的库更优雅,导致代码更短,就用谁。
一切高级语言都是DSL语言,诚哉斯言。
6在NodeList做遍历,map()
dom操作时,有时会遇到NodeList,比如 element.childNodes 返回的就是这种。
一般对array,希望返回另一个数组时用map(), 不希望返回值时用forEach()
如果希望通过map,对每一个元素进行计算,返回1个数组:
const result = myNodeList.map((d)=>{ //do some compute});
会报错:
.map is not a function
官方文档说得很详细,NodeList只是长得像Array,但并不是Array,因为原型链和Array不同。
详见
除了
forEach
方法,NodeList 没有这些类似数组的方法。
官网给出了多种遍历的方法,最简单的就是最老实做for
const results = []; for (let i = 0; i < myNodeList.length; ++i) { results.push(parser_item(myNodeList[i])); }
然而,这也太弱了好吗,10多年前学C++ primer的时候最开始就是学在Vector上遍历 然后push。这TM一点技术含量都没有!
官网其他方法也都没有兴趣,有点过于跑题了。语句要比这个更短,要一眼能看出我是在做遍历map
仔细看文档,发现NodeList有values()方法。在pandas之类的库里,这玩意通常是返回array的,有戏:
试了一下,这个返回的类型是
Object [Array Iterator]
哈哈,果然有戏,既然是个数组迭代器,那么转数组就很显然了(继续Google一番),最终解决方案:
const results = Array.from(myNodeList).map(parser_item);
稍微绕点脖子,但是还是压缩在了1行里,而且肉眼可见 Array map 这些字眼,显然我是在做相关的遍历求值操作。
对于我这种只考虑可读性,不考虑性能的人来说,可以和上面的naive for循环说byebye了!
7 遍历element.attributes
和前面类似,这玩意是个NamedNodeMap。
传统操作
const attrMap = element.attributes;for(let i = 0; i < attrMap.length; i++){ let key = attrMap[i].nodeName; let value = attrMap[i].nodeValue;}
或者不遍历的情况,直接
element.getAttribute(‘属性名’);
那么参考上面的做法,但还是稍微复杂点,要用到Array的reduce
const results = Array.from(element.attributes) .filter((item) => { return !excludes.includes(item.name);}) .reduce((res, item) =>{ res[item.name]=item.value; return res; },{});
遇到两个坑,卡了很长时间。第一个坑是 reduce 的第一个参数累积函数,每次必须要返回累积后的结果 也就是return res; 这里初始值是{},每次往里塞一个属性值。
第二个坑,是py和js完全不同的地方,下面说。
8 判断 元素在数组中
这个是py玩家基本必中的天坑了。
py里 太习惯 了
if x in list_a:
pass
if x not in dict_b:
pass
但是,在js里,in已经被占为其他用途了:
如果指定的 属性在指定的对象或其原型链中,则in
运算符返回true
。
// 数组var trees = new Array("redwood", "bay", "cedar", "oak", "maple");0 in trees // 返回true3 in trees // 返回true6 in trees // 返回false"bay" in trees // 返回false (必须使用索引号,而不是数组元素的值)"length" in trees // 返回true (length是一个数组属性)
'property' in a
大约等于py里的 hasattr()函数
hasattr(a, 'property')
这TM坑爹呢!
a.includes(element)
9判断代码运行在node还是browser
var isBrowser = typeof window !== 'undefined' && ({}).toString.call(window) === '[object Window]';var isNode = typeof global !== "undefined" && ({}).toString.call(global) === '[object global]';