这两天学到了很多.

queryselectorall

OR: chain selectors with commas

document.querySelectorAll('div, p span');
// selects divs, and spans in ps

AND: chain selectors without whitespace

document.querySelectorAll('div.myClass');
// selects divs with the class "myClass"

NOT: :not()-selector

document.querySelectorAll('div:not(.myClass)');
// selects divs that do not have the class "myClass"

等于有很多种:

/* <a> elements with an href containing "example" */
a[href*="example"] {
  font-size: 2em;
}

/* <a> elements with an href ending ".org" */
a[href$=".org"] {
  font-style: italic;
}

/* <a> elements whose class attribute contains the word "logo" */
a[class~="logo"] {
  padding: 2px;
}

数组

链式调用.map().filter()实际上是两次循环, 可以用reduce做成一次循环
//原始的: 
var sources = images.filter(function(img) {
  if (img.src.split('.').pop() === "json") {
    return false; // skip
  }
  return true;
}).map(function(img) { return img.src; });
//reduce版本: 
var sources = images.reduce(function(result, img) {
  if (img.src.split('.').pop() !== "json") {
    result.push(img.src);
  }
  return result;
}, []);
//flatmap版本: 
images.flatMap(({src}) => src.endsWith('.json') && [] || src);

//flatmap可以转化为reduce concat, 不过concat-reduce效率不高.
var arr = [1, 2, 3, 4];
arr.flatMap(x => [x, x * 2]);
// is equivalent to
arr.reduce((acc, x) => acc.concat([x, x * 2]), []);
// [1, 2, 2, 4, 3, 6, 4, 8]

promise

这三种写法基本等价, 除了reject情况的优先处理.

//写法一
const [result1, result2] = await Promise.all([task1(), task2()]);

//写法二
const t1 = task1();
const t2 = task2();

const result1 = await t1;
const result2 = await t2;

//写法三
const [t1, t2] = [task1(), task2()];
const [result1, result2] = [await t1, await t2];
async function mym(i) {
  console.log('start of my script');
  //这个await是必须的.
  await new Promise((resolve, reject) => {
    if(i>10){//这里会引起一个隐藏的bug, 就是i<10时永远也不会resolve.
      chrome.tabs.create({ url: "about:blank", active: false }, tab => {
        console.log('Tab created: ' + tab.id);
        if (chrome.runtime.lastError) {
          reject(new Error(chrome.runtime.lastError));
        } else if(i>5){ //这里会引起一个隐藏的bug, 就是i<5时永远也不会resolve.
          resolve(tab);
        }
      });
    }
  })
  console.log('end of my script');//很可能这里永远不会执行. 因此编码时要写足resolve
}

//因此要改造成下面这样才可以: 
await new Promise((resolve,reject) => {
  if(ua.length=0) resolve();
  chrome.tabs.query({windowId},tabs => {
    if(!(tabs.length<config.tablimit)) resolve();
    chrome.tabs.create({url: ua[0],active: false},tab => {
      dosomething();
      resolve();
    });
  });
})

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Using_promises

事件的target

e.currentTarget; 保证了注册事件的父元素, 而不是触发事件的子元素.
e.target
e.stopPropagation();
e.preventDefault();

element的value

//todo待验证, 到popup页面测试下.

	//	document.querySelector('input[name = "code"]').value = details.setting; 这种写法此处并不生效
				document.querySelector('input[name = "code"][value='+details.setting+']').checked=true;
		
尾递归
	if (condition) {
		await sleep(time);
	 return	basermain({lastpics,lasthrefs,time});//尾递归
	}

这样就不会堆栈溢出了.

解构有iterator要求

//这两个写法会报错, undefined不是iterable
let ua=[...{}.url];
let ua=[...({}).url];

//这两个写法ok
let ua=[...{url:[]}.url];
let ua=[...({url:[]}).url];