web知识点-记录

2017-05-01  本文已影响82人  wwmin_

技术点: 不定期更新补充

  .ellipsis{
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
  }
const keys = Array.from(document.querySelectorAll('.key'));
  keys.forEach(key => key.addEventListener('transitionend', removeTransition));
:root { --color: purple; }
div { --color: green; }
#alert { --color: red; }
* { color: var(--color); }
body {
  --size: 20;   
  font-size: calc(var(--size) * 1px);
}
选择器 例子 例子描述 CSS
.class .intro 选择 class="intro" 的所有元素。 1
#id #firstname 选择 id="firstname" 的所有元素。 1
* * 选择所有元素。 2
element p 选择所有 <p> 元素。 1
element,element div,p 选择所有 <div> 元素和所有 <p> 元素。 1
element element div p 选择 <div> 元素内部的所有 <p> 元素。 1
element>element div>p 选择父元素为 <div> 元素的所有 <p> 元素。 2
element+element div+p 选择紧接在 <div> 元素之后的所有 <p> 元素。 2
[attribute] [target] 选择带有 target 属性所有元素。 2
[attribute=value] [target=_blank] 选择 target="_blank" 的所有元素。 2
[attribute~=value] [title~=flower] 选择 title 属性包含单词 "flower" 的所有元素。 2
[attribute|=value] [lang|=en] 选择 lang 属性值以 "en" 开头的所有元素。 2
:link a:link 选择所有未被访问的链接。 1
:visited a:visited 选择所有已被访问的链接。 1
:active a:active 选择活动链接。 1
:hover a:hover 选择鼠标指针位于其上的链接。 1
:focus input:focus 选择获得焦点的 input 元素。 2
:first-letter p:first-letter 选择每个 <p> 元素的首字母。 1
:first-line p:first-line 选择每个 <p> 元素的首行。 1
:first-child p:first-child 选择属于父元素的第一个子元素的每个 <p> 元素。 2
:before p:before 在每个 <p> 元素的内容之前插入内容。 2
:after p:after 在每个 <p> 元素的内容之后插入内容。 2
:lang(language) p:lang(it) 选择带有以 "it" 开头的 lang 属性值的每个 <p> 元素。 2
element1~element2 p~ul 选择前面有 <p> 元素的每个 <ul> 元素。 3
[attribute^=value] a[src^="https"] 选择其 src 属性值以 "https" 开头的每个 <a> 元素。 3
[attribute$=value] a[src$=".pdf"] 选择其 src 属性以 ".pdf" 结尾的所有 <a> 元素。 3
[attribute*=value] a[src*="abc"] 选择其 src 属性中包含 "abc" 子串的每个 <a> 元素。 3
:first-of-type p:first-of-type 选择属于其父元素的首个 <p> 元素的每个 <p> 元素。 3
:last-of-type p:last-of-type 选择属于其父元素的最后 <p> 元素的每个 <p> 元素。 3
:only-of-type p:only-of-type 选择属于其父元素唯一的 <p> 元素的每个 <p> 元素。 3
:only-child p:only-child 选择属于其父元素的唯一子元素的每个 <p> 元素。 3
:nth-child(n) p:nth-child(2) 选择属于其父元素的第二个子元素的每个 <p> 元素。 3
:nth-last-child(n) p:nth-last-child(2) 同上,从最后一个子元素开始计数。 3
:nth-of-type(n) p:nth-of-type(2) 选择属于其父元素第二个 <p> 元素的每个 <p> 元素。 3
:nth-last-of-type(n) p:nth-last-of-type(2) 同上,但是从最后一个子元素开始计数。 3
:last-child p:last-child 选择属于其父元素最后一个子元素每个 <p> 元素。 3
:root :root 选择文档的根元素。 3
:empty p:empty 选择没有子元素的每个 <p> 元素(包括文本节点)。 3
:target #news:target 选择当前活动的 #news 元素。 3
:enabled input:enabled 选择每个启用的 <input> 元素。 3
:disabled input:disabled 选择每个禁用的 <input> 元素 3
:checked input:checked 选择每个被选中的 <input> 元素。 3
:not(selector) :not(p) 选择非 <p> 元素的每个元素。 3
::selection ::selection 选择被用户选取的元素部分。 3
.plates input + label:before {
   content: '⬜️'
   margin-right: 10px;
   }
.plates input:checked + label:before {
   content: '🌮';
   }
localstorage.setItem("key","value");
localstorage.getItem("key");
localstorage.removeItem("key");//删除键
localstorage.clear();//清除所有键值对
localstorage.key(index);//获取localstorage的属性名称
localstorage.length;//localstorage键值对数量
{
  "name": "gum",
  "version": "1.0.0",
  "description": "",
  "main": "scripts.js",
  "scripts": {
    "start" : "browser-sync start --server --files '*.css, *.html, *.js'"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "browser-sync": "^2.12.5"
  }
}
const divs = document.querySelectorAll('div');
  const button = document.querySelector('button');

  function logText(e) {
    console.log(this.classList.value);
    // e.stopPropagation(); // stop bubbling!
    // console.log(this);
  }

  divs.forEach(div => div.addEventListener('click', logText, {
    capture: false,
    once: false
  }));

  button.addEventListener('click', () => {
    console.log('Click!!!');
  }, {
    once: true
  });
.hole:after {
  display: block;
  background: url(dirt.svg) bottom center no-repeat;
  background-size:contain;
  content:'';
  width: 100%;
  height:70px;
  position: absolute;
  z-index: 2;
  bottom:-30px;
}
function chen(x){
 if(x<=1)return 1;
 else arguments.callee(x-1); //此处相当于else chen(x-1);
(function a(){
  b();
 })();
function b(){
console.log(arguments.callee.caller); //相当于b.caller ==>输出函数a
};
nav a{
     color:red;
   }
head nav a{
      color:green;
 }
head nav a + a{
    color:black;
}

scss:

nav {
    a{
        color:red;
        head & { //&代表父级
            color:green;
            head & + a{ //+ 代表下一个
                color:black;
            }
        }
    }
}
p  {  white-space: nowrap  }
normal  默认。空白会被浏览器忽略。
pre 空白会被浏览器保留。其行为方式类似 HTML 中的 <pre> 标签。
nowrap  文本不会换行,文本会在在同一行上继续,直到遇到 <br> 标签为止。
pre-wrap    保留空白符序列,但是正常地进行换行。
pre-line    合并空白符序列,但是保留换行符。
inherit 规定应该从父元素继承 white-space 属性的值。
var reg = /^https?:\/\/[a-zA-Z0-9-._\/]+/gi;
reg.test("http://www.baidu.com");//true
reg.test("http://www.baidu.com");//false
//方法一:去掉g
var reg = /^https?:\/\/[a-zA-Z0-9-._\/]+/i;
//方法二: test之后,执行reg.lastIndex=0
reg.test("http://www.baidu.com");//true
reg.lastIndex=0;
let elemIF = document.createElement("iframe");
                        elemIF.src = 'http://a.b.com/1.';
                        elemIF.style.display = "none";
                        document.body.appendChild(elemIF);

a标签的href 加上download属性方式:

<a href="/images/myw3schoolimage.jpg" download="w3logo">

URL.createObjectURL的参数是File对象或者Blob对象,File对象也就是通过input[type=file]选择的文件,Blob对象是二进制大对象

function downloadFile(fileName, content){
    var aLink = document.createElement('a');
    var blob = new Blob([content]);
    //创建点击事件
    var evt = document.createEvent("HTMLEvents");
    evt.initEvent("click", false, false);//initEvent 不加后两个参数在FF下会报错
    aLink.download = fileName;
    aLink.href = URL.createObjectURL(blob);
    aLink.dispatchEvent(evt);
}
function tounicode(data) {
  if (data == '') return '请输入汉字';
  var str = '';
  for (var i = 0; i < data.length; i++) {
    str += "\\u" + parseInt(data[i].charCodeAt(0), 10).toString(16);
  }
  return str;
}
function tohanzi(data) {
  if (data == '') return '请输入十六进制unicode';
  data = data.split("\\u");
  var str = '';
  for (var i = 0; i < data.length; i++) {
    str += String.fromCharCode(parseInt(data[i], 16).toString(10));
  }
  return str;
}
<template>
  <transition :name="transitionName">
    <div class="back-to-top" @click="backToTop" v-show="visible" :style="customStyle" title="返回顶部">
      <svg width="16" height="16" viewBox="0 0 17 17" xmlns="http://www.w3.org/2000/svg"
           class="Icon Icon--backToTopArrow" aria-hidden="true" style="height: 16px; width: 16px;">
        <title>回到顶部</title>
        <g>
          <path
            d="M12.036 15.59c0 .55-.453.995-.997.995H5.032c-.55 0-.997-.445-.997-.996V8.584H1.03c-1.1 0-1.36-.633-.578-1.416L7.33.29c.39-.39 1.026-.385 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.004z"
            fill-rule="evenodd"></path>
        </g>
      </svg>
    </div>
  </transition>
</template>
<script>
  let dom = null;//定义dom 默认为window
  let isWindow = false;//判断是否为window
  export default {
    name: 'BackToTop',
    props: {
      //dom id , 如果不给值,则整个默认为window
      domID: {
        type: String,
        default: ""
      },
      visibilityHeight: {
        type: Number,
        default: 300
      },
      backPosition: {
        type: Number,
        default: 0
      },
      customStyle: {
        type: Object,
        default: () => ({
          right: '50px',
          bottom: '50px',
          width: '40px',
          height: '40px',
          'border-radius': '4px',
          'line-height': '45px',
          background: '#e7eaf1'
        })
      },
      transitionName: {
        type: String,
        default: 'fade'
      }
    },
    data() {
      return {
        visible: false,
        interval: null
      }
    },
    mounted() {
      //判断是否为window 后面会分别采用不同的方法
      let d = document.getElementById(this.domID);
      if (!!d) {
        dom = d;
        isWindow = false;
      } else {
        isWindow = true;
        dom = window;
      }
      dom.addEventListener('scroll', this.handleScroll)
    },
    beforeDestroy() {
      dom.removeEventListener('scroll', this.handleScroll);
      if (this.interval) {
        clearInterval(this.interval);
        this.interval = null;
      }
    },
    methods: {
      handleScroll(e) {
        this.visible = isWindow ? dom.pageYOffset > this.visibilityHeight : dom.scrollTop > this.visibilityHeight;
      },
      backToTop() {
        if (this.interval !== null) return;
        const start = isWindow ? window.pageYOffset : dom.scrollTop;
        let i = 0;
        this.interval = setInterval(() => {
          const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 200));
          if (next <= this.backPosition) {
            isWindow ? window.scrollTo(0, this.backPosition) : dom.scrollTop = this.backPosition;
            clearInterval(this.interval);
            this.interval = null;
          } else {
            isWindow ? window.scrollTo(0, next) : dom.scrollTop = next;
          }
          i++
        }, 16.7);
      },
      easeInOutQuad(t, b, c, d) {
        if ((t /= d / 2) < 1) return c / 2 * t * t + b;
        return -c / 2 * (--t * (t - 2) - 1) + b
      }
    }
  }
</script>
<style scoped>
  .back-to-top {
    position: fixed;
    display: inline-block;
    text-align: center;
    cursor: pointer;
  }
  .back-to-top:hover {
    background: #d5dbe7;
  }
  .fade-enter-active,
  .fade-leave-active {
    transition: opacity .5s;
  }
  .fade-enter,
  .fade-leave-to {
    opacity: 0
  }
  .back-to-top .Icon {
    fill: #9aaabf;
    background: none;
  }
</style>

~~true === 1
~~false === 0
~~"" === 0
~~[] === 0
~~undefined === 0
~~!undefined === 1
~~null === 0
~~!null === 1
~~4.9===4
1.3 | 0         // 1
-1.9 | 0        // -1
const num=3;
!!(num & 1)                 // true
!!(num % 2)                 // true
var a=[1,2,[1,2,3],[2,3,[2,3,4]]];
var result=a.toString().split(',');// ["1", "2", "1", "2", "3", "2", "3", "2", "3", "4"]

function flatten(arr){
    return arr.reduce(function(prev,item){
        return prev.concat(Array.isArray(item)?flatten(item):item);
    },[]);
}

function flatten(arr){
    while(arr.some(item=>Array.isArray(item)){
        arr = [].concat(...arr);
    }
    return arr;
}
const flatten = (arr, depth = 1) =>
  depth != 1
    ? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flatten(v, depth - 1) : v), [])
    : arr.reduce((a, v) => a.concat(v), []);
flatten([1, [2], 3, 4]);                             // [1, 2, 3, 4]
flatten([1, [2, [3, [4, 5], 6], 7], 8], 2);           // [1, 2, 3, [4, 5], 6, 7, 8]
function sleep(delay){
  return new Promise(reslove=>{
           setTimeout(reslove,delay)
    })
}
!async function test(){
    const t1=+new Date();
    await sleep(3000);
    const t2=+new Date()
    console.log(t2-t1);
}()
+new Date() ;//最简洁
ToNumber(new Date());
new Date().getTime();
var a=[1,1,'1','2',1];
const unique=a=>[...new Set(a)];
const a=1234567;
//正则方式
function formatNumber(str){
    return str.replace(/\B(?=(\d{3})+(?!\d))/g,',')
}
//api版
a.toLocaleString('en-US');
a.toLocaleString(10);
var a=1,b=2;
[a,b]=[b,a];
let qrcode=('000000' + Math.floor(Math.random() * 999999)).slice(-6);
'componentMapModelRegistry'.match(/^[a-z][a-z0-9]+|[A-Z][a-z0-9]*/g).join('_').toLowerCase();  
//component_map_model_registry
//query("?a=1&b=2") ==> {a:"1",b:"2"}
const query = (search = '') => ((querystring = '') => (q => (querystring.split('&').forEach(item => (kv => kv[0] && (q[kv[0]] = kv[1]))(item.split('='))), q))({}))(search.split('?')[1])
//去掉箭头函数写法
const qeury = function (search = '') {
  return function (querystring = '') {
    return function (q) {
      return querystring.split('&').forEach(function (item) {
        return function (kv) {
          return kv[0] && (q[kv[0]] = kv[1])
        }(item.split('='))
      }), q
    }({})
  }(search.split('?')[1])
};
//Math.hypot([x[,y[,…]]])函数返回它的所有参数的平方和的平方根
Math.hypot(3,4) //=> 5
//字符串
var s="abc";
s.indexOf("a");  //0
//数组
var a=["aa","bb","cc"];
a.indexOf("aa");//0
// 1. <<
1<<1  // 2
1<<2 //4
1<<3 //8
...
1<<n //等价于=> 1*2^n

// 2.>>
8>>1 //4
8>>2 //2
8>>3 //1
...
8>>n // 等级于 => 8%2^n
var person={name:"aaa",age:1};
Object.keys(person);
Object.getOwnPropertyNames(person);
Reflect.ownKeys(person);
for(let iten in person){console.log(item)};
Object.getOwnPropertySymbols(person);//获取对象的symbol键值
var a=new Array(4);
a.forEach(p=>console.log(p));//没有打印
a=[1, null, NaN, empty];
var ae=a.entries();
ae.next().value; //[0,1];
ae.next().value; //[1,null];
ae.next().value; //[2,NaN];
ae.next().value; //[3,undefined];
  Math.seed = 5;
  Math.seededRandom = function (max, min) {
    max = max || 1;
    min = min || 0;
    Math.seed = (Math.seed * 9301 + 49297) % 233280;
    var rnd = Math.seed / 233280.0;
    return min + rnd * (max - min);
  };
  for (var i = 0; i < 5; i++) {
    console.log(Math.seededRandom());
  }
//结果如下
  0.4106738683127572
  0.8889703360768175
  0.5244170096021948
  0.8139274691358025
  0.5507115912208504
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <title> 页面名称 </title>
  <style type="text/css">
    .main dd {
      display: none;
    }
    .main dt:hover+dd, .main dd:hover {
      display: block;
    }
  </style>
</head>
<body>
<div class="main">
  <dt><a href="#">中心信息</a></dt>
  <dd><a href="#">中心介绍</a>
    <a href="#" >荣誉奖项</a>
    <a href="#" >中心环境</a>
    <a href="#" >中心地址</a>
    <a href="#" >联系我们</a> </dd>
</div>
</body>
</html>
  var logger = value => {
    if (Object.prototype.toString.call(value) !== "[object String]") {
      value = JSON.stringify(value);
    }
    let div = document.createElement("div");
    div.innerText = value;
    document.body.appendChild(div);
  };
  // 定义一个observe方法
  function defineReactive(data, key, val) {
    Object.defineProperty(data, key, {
      enumerable: true,
      configurable: true,
      get: function defineGet() {
        console.log(`get key: ${key} val: ${val}`);
        return val
      },
      set: function defineSet(newVal) {
        console.log(`set key: ${key} val: ${newVal}`);
        // 此处将新的值赋给val,保存在内存中,从而达到赋值的效果
        val = newVal
      }
    })
  }

  // 遍历对象的属性,使之观察每个数值值
  function observe(data) {
    Object.keys(data).forEach(key => {
      defineReactive(data, key, data[key]);
    })
  }

var person={name:"wwmin"};
observe(person);
person.name="hello world.";// => set key: name val: hello world.
//十进制转其他  
var x=110;  
console.log(x);    //110
console.log(x.toString(8));  //156
console.log(x.toString(32));  //3e
console.log(x.toString(16));  //6e
//其他转十进制  
var x='110';  
console.log(parseInt(x,2));  //6
console.log(parseInt(x,8));  //72
console.log(parseInt(x,16));  //272
//其他转其他  
//先用parseInt转成十进制再用toString转到目标进制  
console.log(String.fromCharCode(parseInt(141,8))) ; //a
console.log(parseInt('ff',16).toString(2)); //11111111
var m=new Map();
//或者直接初始话
var m=new Map([[1,"a"],[2,"b"],[3,"c"]]);
m.constructor===Map;//true
//Map属性和方法
m.set(1,"aa");
m.set(1,"a");//会覆盖上面的键值
m.set(2,"b");
m.set(3,"c");
m.size;//3
m.get(1);//a
m.has(1);//true
m.keys();//MapIterator {1, 2, 3}
console.log([...m.keys()]);//[1,2,3]  ,转换成标准数组
m.values();//MapIterator {"a", "b", "c"}
console.log([...m.values()]);//["a", "b", "c"]
m.entries();//MapIterator {1 => "a", 2 => "b", 3 => "c"}
console.log([...m.entries()]);//[[1, "a"], [2, "b"], [3, "c"]]
m.forEach((v,k,p)=>console.log(v,k,p));//a 1 Map(3) {1 => "a", 2 => "b", 3 => "c"},b 2 Map(3) {1 => "a", 2 => "b", 3 => "c"},c 3 Map(3) {1 => "a", 2 => "b", 3 => "c"}
m.delete(1);//true;
m.has(1);//false
m.clear();
var s=new Set();
//或者直接初始化
var s=new Set([1,2,3]);
s.constructor===Set;//true
s.add(1);
s.size;//3
s.has(1);//true
s.keys();//SetIterator {1, 2, 3}
console.log([...s.keys()]);//[1,2,3]
s.values();//等同于s.keys();
s.entries();//SetIterator {1, 2, 3}
console.log([...m.entries()]);//[[1, 1], [2, 2], [3, 3]]
s.forEach((v,k,p)=>console.log(v,k,p));//1 1 Set(3){1,2,3},2 2 Set(3){1,2,3},3 4 Set(3){1,2,3}
s.delete(1);//true
s.has(1);//false
s.clear();
const s = '1997,John Doe,US,john@doe.com,New York';
const {2:country,4:state}=s.split(","); //2为split之后的数组下标,country为指定的变量
console.log(country);//US
console.log(state);//New York
let {_internal, tooBig, ...cleanObject} = {el1: '1', _internal:"secret", tooBig:{}, el2: '2', el3: '3'};

console.log(cleanObject);                         // {el1: '1', el2: '2', el3: '3'}
let object1 = { a:1, b:2,c:3 }
let object2 = { b:30, c:40, d:50}
let merged = {…object1, …object2} //spread and re-add into merged
console.log(merged) // {a:1, b:30, c:40, d:50}

注意:第二个对象中的属性 b 和 c 的值把第一个对象中属性 b 与 c 的值覆盖掉了

var car = {
  model: 'bmw 2018',
  engine: {
    v6: true,
    turbo: true,
    vin: 12345
  }
}
const modelAndVIN = ({model, engine: {vin}}) => {
  console.log(`model: ${model} vin: ${vin}`);
}
modelAndVIN(car); // => model: bmw 2018  vin: 12345
function getWaterState(tempInCelsius) {
  let state;
  switch (true) {
    case (tempInCelsius <= 0): 
      state = 'Solid';
      break;
    case (tempInCelsius > 0 && tempInCelsius < 100): 
      state = 'Liquid';
      break;
    default: 
      state = 'Gas';
  }
  return state;
}
//await 多个 async 函数并等待他们执行完成,我们可以使用 Promise.all:
await Promise.all([anAsyncCall(), thisIsAlsoAsync(), oneMore()])
const pureObject = Object.create(null);
console.log(pureObject); //=> {}
console.log(pureObject.constructor); //=> undefined
console.log(pureObject.toString); //=> undefined
console.log(pureObject.hasOwnProperty); //=> undefined
const obj = { 
 foo: { bar: [11, 22, 33, 44], baz: { bing: true, boom: 'Hello' } } 
};

// 第三个参数为格式化需要的空格数目
JSON.stringify(obj, null, 4); 
// =>"{
// =>    "foo": {
// =>        "bar": [
// =>            11,
// =>            22,
// =>            33,
// =>            44
// =>        ],
// =>        "baz": {
// =>            "bing": true,
// =>            "boom": "Hello"
// =>        }
// =>    }
// =>}"
//对象解构,且有默认值,并且参数可选
function doSomething({ foo = 'Hi', bar = 'Yo!', baz = 13 } = {}) {
  // ...
}

注意,传入参数为undefined或者不传入的时候会使用默认参数,但是传入null还是会覆盖默认参数。

async function getFullPost(){
  return await Promise.all([
     fetch('/post'),
     fetch('/comments')
  ]);
}
const [post, comments] = getFullPost();
mandatory = ( ) => {
  throw new Error('Missing parameter!');
}
foo = (bar = mandatory( )) => {            // 这里如果不传入参数,就会执行manadatory函数报出错误
  return bar;
}
function a(n){
  return {value:n}
}
//简写为
let a=n=>({value:n})
function foo(){
    if(a !== b){
        console.log('aaa')
    }else{
        console.log('bbb')
    }
}

// 优化后
function foo(){
    if(a != b){
        foo = function(){
            console.log('aaa')
        }
    }else{
        foo = function(){
            console.log('bbb')
        }
    }
    return foo();
}
var sca = function() {
    console.log('msg')
    sca = function() {
        console.log('foo')
    }
}
sca()        // msg
sca()        // foo
sca()        // foo
<input type="text" placeholder="请输入手机号码" maxlength="11" />

上面的maxlength是有效的,但是将type="number"后将失去效果,此时可以使用type="tel" 解决

<input type="tel" placeholder="请输入手机号码" maxlength="11" />

不过此时数字键盘会存在一个'-'的固话符号,此影响较小可忽略,如果为了可拓展性,可用input事件写JavaScript取解决,即在oninput onpropertychange事件中取截取字符串长度即可.

 <input value="上传图片" type="file" id="file" name="file" onchange="show(this.files)" />
 <br />
 <img height="50" width="50" id="img"  />
    function show(f) {
        var str = "";
        for (var i = 0; i < f.length; i++) {
            var reader = new FileReader();
            reader.readAsDataURL(f[i]);
            reader.onload = function (e) {
                str += "<img  height='50' width='50' id='img' src='" + e.target.result + "'/>";
                $("#img")[0].outerHTML = str;
            }
        }        
    }
'12' * 1            // 12
'aa' * 1            // NaN
null * 1            // 0
undefined * 1    // NaN
1  * { valueOf: ()=>'2' }        // 2
+ '12'            // 12
+ 'aa'               // NaN
+ ''                    // 0
+ null              // 0
+ undefined    // NaN
+ { valueOf: ()=>'2' }    // 2
'' + {toString:()=>'S',valueOf:()=>'J'}// J  //toString()和valueOf同时存在则用valueOf()
const compact = arr => arr.filter(Boolean);
compact([0, 1, false, 2, '', 3, 'a', 'e' * 23, NaN, 's', 34])             // [ 1, 2, 3, 'a', 's', 34 ]
const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`)
round(1.345, 2)                 // 1.35
round(1.345, 1)                 // 1.3
var cars = ['BMW','Benz', 'Benz', 'Tesla', 'BMW', 'Toyota'];
var carsObj = cars.reduce(function (obj, name) {
  obj[name] = obj[name] ? ++obj[name] : 1;
  return obj;
}, {});
carsObj; // => { BMW: 2, Benz: 2, Tesla: 1, Toyota: 1 }
const addZero = (num, len = 2) => (`0${num}`).slice(-len);
//Returns 0 if balanced.
const isParensBalanced = (str) => {
  return str.split('').reduce((counter, char) => {
    if(counter < 0) { //matched ")" before "("
      return counter;
    } else if(char === '(') {
      return ++counter;
    } else if(char === ')') {
      return --counter;
    }  else { //matched some other char
      return counter;
    }
    
  }, 0); //<-- starting value of the counter
}
isParensBalanced('(())') // 0 <-- balanced
isParensBalanced('(asdfds)') //0 <-- balanced
isParensBalanced('(()') // 1 <-- not balanced
isParensBalanced(')(') // -1 <-- not balanced
var cars = ['BMW','Benz', 'Benz', 'Tesla', 'BMW', 'Toyota'];
var carsObj = cars.reduce(function (obj, name) { 
   obj[name] = obj[name] ? ++obj[name] : 1;
  return obj;
}, {});
carsObj; // => { BMW: 2, Benz: 2, Tesla: 1, Toyota: 1 }
/**
 * js 实现 linq groupBy
 *
 * @param {*} array
 * @param {*} f =>item.name || f=>[item.name,item.Average]
 * @returns
 */
function groupBy(array, f) {
  let groups = {};
  array.forEach(o => {
    let group = JSON.stringify(f(o));
    groups[group] = groups[group] || [];
    groups[group].push(o);
  });
  return Object.keys(groups).map(group => groups[group])
}

// 使用
let list = [
{ "name": "John", "Average": 10, "High": 10, "DtmStamp": 1358226000000 },
{"name": "Jane","Average":10,"High":92,"DtmStamp":1358226000000},
{"name": "Jane","Average":10,"High":45,"DtmStamp":1358226000000},
{"name": "John","Average":10,"High":87,"DtmStamp":1358226000000},
{"name": "Jane","Average":10,"High":10,"DtmStamp":1358226060000},
{"name": "John","Average":15,"High":87,"DtmStamp":1358226060000},
{"name": "John","Average":15,"High":45,"DtmStamp":1358226060000},
{"name": "Jane","Average":15,"High":92,"DtmStamp":1358226060000}
];
// 使用1
let sort1 = groupBy(list, item => {
  return [item.name, item.Average];
})
// 结果
/** 
[ [ { name: 'John', Average: 10, High: 10, DtmStamp: 1358226000000 },​​​​​
​​​​​    { name: 'John', Average: 10, High: 87, DtmStamp: 1358226000000 },​​​​​
​​​​​    { name: 'John', Average: 15, High: 87, DtmStamp: 1358226060000 },​​​​​
​​​​​    { name: 'John', Average: 15, High: 45, DtmStamp: 1358226060000 } ],​​​​​
​​​​​  [ { name: 'Jane', Average: 10, High: 92, DtmStamp: 1358226000000 },​​​​​
​​​​​    { name: 'Jane', Average: 10, High: 45, DtmStamp: 1358226000000 },​​​​​
​​​​​    { name: 'Jane', Average: 10, High: 10, DtmStamp: 1358226060000 },​​​​​
​​​​​    { name: 'Jane', Average: 15, High: 92, DtmStamp: 1358226060000 } ] ]​​​​​
**/

// 使用2
let sort2 = groupBy(list, item => {
  return item.name;
})
// 结果
/** 
[ [ { name: 'John', Average: 10, High: 10, DtmStamp: 1358226000000 },​​​​​
​​​​​    { name: 'John', Average: 10, High: 87, DtmStamp: 1358226000000 } ],​​​​​
​​​​​  [ { name: 'Jane', Average: 10, High: 92, DtmStamp: 1358226000000 },​​​​​
​​​​​    { name: 'Jane', Average: 10, High: 45, DtmStamp: 1358226000000 },​​​​​
​​​​​    { name: 'Jane', Average: 10, High: 10, DtmStamp: 1358226060000 } ],​​​​​
​​​​​  [ { name: 'John', Average: 15, High: 87, DtmStamp: 1358226060000 },​​​​​
​​​​​    { name: 'John', Average: 15, High: 45, DtmStamp: 1358226060000 } ],​​​​​
​​​​​  [ { name: 'Jane', Average: 15, High: 92, DtmStamp: 1358226060000 } ] ]​​​​​
**/
* {
-webkit-touch-callout:none;
-webkit-user-select:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
}
 input {      
   -webkit-user-select:auto; /*webkit浏览器*/     
}  
 try { 
        if(x == "")  throw "为空";
    }catch(err) {
        message.innerHTML = "输入的值 " + err;
    }finally {//总是会会执行到此处
        document.getElementById("demo").value = "";
    }
let a=[1,2,3];
let sum=a.reduce((p,t)=>p+t,0);

eval

let a=[1,2,3];
let sum=eval(a.join('+'));
function getExt(fileName){
  return fileName.substring(fileName.lastIndexOf('.')+1);
}
// 生成guid,主要用于生成随机文件名
function newGuid() {
    function S4() {
        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
    }
    return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
}
const firstUpperCase = ([first, ...rest]) => first.toUpperCase() + rest.join('');
<ul></ul>
<ul>
  <li>item1</li>
  <li>item2</li>
  <li>item3</li>
  <li>item4</li>
</ul>
<style lang="scss">
ul {
  &:empty {
    width: 140px;
    height: 226px;
    background: url(https://ws3.sinaimg.cn/large/006tNbRwly1fwln1ad006g303w04sdlq.gif) no-repeat;
    background-size: cover; 
  }
}
</style>
  matchParenthesisValue(string: string, size: "small" | "middle" | "large" = "small"): Array<string> {
    var regex1 = /\((.+?)\)/g;   // () 小括号
    var regex2 = /\[(.+?)\]/g;   // [] 中括号
    var regex3 = /\{(.+?)\}/g;  // {} 花括号,大括号
    switch (size) {
      case "small":
        return string.match(regex1).map(p => p.replace(/[\(|\)]/ig, ''));
      case "middle":
        return string.match(regex2).map(p => p.replace(/[\[|\\]/ig, ''));
      case "large":
        return string.match(regex3).map(p => p.replace(/[\{|\}]/ig, ''));
      default:
        return [];
    }
  }
 /**
   *获取addDateCount前后的日期
   *
   * @param {number} addDateCount 日期天数,正值为之后天数,负值为之前天数
   * @returns date string
   */
  getFrontBackDate(addDateCount: number) {
    let date = new Date();
    date.setDate(date.getDate() + addDateCount);//获取addDayCount天后的日期
    return this.formatDate(date);
  },
 /**
   *格式化时间 型为: 2017-01-01
   *
   * @param {(string | Date)} date
   * @returns {string}
   */
  formatDate(date: string | Date): string {
    if (!date) return "";
    if (typeof date === "string") date = date.replace("T", " "); // 服务器返回的时间中含有T,部分浏览器解释不正确
    date = new Date(date);
    const year = date.getFullYear();
    const month = date.getMonth() + 1;
    const day = date.getDate();
    return [year, month, day].map(this.formatNumber).join("-");
  },
  /**
   *将个位数补上0
   *
   * @param {*} n
   * @returns
   */
  formatNumber(n) {
    n = n.toString();
    return n[1] ? n : "0" + n;
  },
import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'
 
// Require in a base component context
const requireComponent = require.context(
 './components', false, /base-[\w-]+\.vue$/
)
 
requireComponent.keys().forEach(fileName => {
 // Get component config
 const componentConfig = requireComponent(fileName)
 
 // Get PascalCase name of component
 const componentName = upperFirst(
  camelCase(fileName.replace(/^\.\//, '').replace(/\.\w+$/, ''))
 )
 
 // Register component globally
 Vue.component(componentName, componentConfig.default || componentConfig)
})
import auth from './modules/auth'
import posts from './modules/posts'
import comments from './modules/comments'
// ...
 
export default new Vuex.Store({
 modules: {
  auth,
  posts,
  comments,
  // ...
 }
})

精简的做法和上面类似,也是运用 require.context()读取文件,代码如下:

import camelCase from 'lodash/camelCase'
const requireModule = require.context('.', false, /\.js$/)
const modules = {}
requireModule.keys().forEach(fileName => {
 // Don't register this file as a Vuex module
 if (fileName === './index.js') return
 
 const moduleName = camelCase(
  fileName.replace(/(\.\/|\.js)/g, '')
 )
 modules[moduleName] = {
        namespaced: true,
        ...requireModule(fileName),
       }
})
export default modules

这样我们只需如下代码就可以了:

import modules from './modules'
export default new Vuex.Store({
 modules
})
function Person(name) {
    this.name = name;
}
let p = new Person('Tom');
//问题:
p.__proto__===Person.prototype //true
Person.__proto__===Function.prototype ;//true

var foo={};
var F=function(){};
Object.prototype.a='value a';
Function.prototype.b = 'value b';

console.log(foo.a)   ;//value a
console.log(foo.b)    ;//undefined
console.log(F.a)     ;//value a
console.log(F.b)    ;//value b
function Person(name) {
    this.name = name
    return name;
}
let p = new Person('Tom');//{name: 'Tom'}
//若改为:
function Person(name) {
    this.name = name
    return {}
}
let p = new Person('Tom');//{}
function Person (name) {
    this.name = name;
}
function Student () {}
Student.prototype = Person.prototype;
Student.prototype.constructor = Student;
let s = new Student('Tom');
console.log(s instanceof Person); // 返回 true
// let p = new Person()
let p = (function () {
    let obj = {};
    obj.__proto__ = Person.prototype;
    // 其他赋值语句...
    return obj;
})(); //p={}

下面通过代码阐述instanceof的内部机制,假设现在有x instanceof y一条语句,则其内部实际做了如下判断:

while(x.__proto__!==null) {
    if(x.__proto__===y.prototype) {
        return true;
        break;
    }
    x.__proto__ = x.__proto__.proto__;
}
if(x.__proto__==null) {return false;}

x会一直沿着隐式原型链proto向上查找直到x.proto.proto......===y.prototype为止,如果找到则返回true,也就是x为y的一个实例。否则返回false,x不是y的实例。

function F() {}
function O() {}

O.prototype = new F();
var obj = new O();

console.log(obj instanceof O); // true
console.log(obj instanceof F); // true
console.log(obj.__proto__ === O.prototype); // true
console.log(obj.__proto__.__proto__ === F.prototype); // true

根据new 的内部机制改写上面代码

function F() {}
function O() {}
var obj = (function () {
    var obj1 = {};
    obj1.__proto__ = F.prototype; // new F();
    O.prototype = obj1; // O.prototype = new F();
    obj.__proto__ = O.prototype; // new O();
    obj.__proto__ = obj1;
    return obj;
})

结合instanceof内部机制很容易得出正确答案。
如果稍微调整一下代码顺序,结果将迥然不同

function F() {};
function O() {};

var obj = new O();
O.prototype = new F();

console.log(obj instanceof O); // false
console.log(obj instanceof F); // false
console.log(obj.__proto__ === O.prototype); // false
console.log(obj.__proto__.__proto__ === F.prototype); // false

上个图,压压惊:


prototype
for (var key of Object.keys(someObject)) {
  console.log(key + ": " + someObject[key]);
}

遍历map对象时适合用解构,例如;

for (var [key, value] of phoneBookMap) {
   console.log(key + "'s phone number is: " + value);
}

当你为对象添加myObject.toString()方法后,就可以将对象转化为字符串,同样地,当你向任意对象添加myObject[Symbol.iterator]方法,就可以遍历这个对象了。
for...of的步骤
for-of循环首先调用集合的Symbol.iterator方法,紧接着返回一个新的迭代器对象。迭代器对象可以是任意具有.next()方法的对象;for-of循环将重复调用这个方法,每次循环调用一次。举个例子

var zeroesForeverIterator = {
 [Symbol.iterator]: function () {
   return this;
  },
  next: function () {
  return {done: false, value: 0};
 }
};
function* gen() {
  yield 1;
  yield 2;
  yield 3;
  yield 4;
}

打印这个函数后发现了一个熟悉的函数,next() 方法,我们把 gen 实例化一下,执行一下它的 next() 来看看结果:

let g=gen();
g.next();// => {value: 1, done: false}
g.next();// => {value: 2, done: false}
g.next();// => {value: 3, done: false}
g.next();// => {value: 4, done: false}
g.next();// => {value: undefined, done: true

到这里,我们已经知道,Generator 可以实例化出一个 iterator ,并且这个 yield 语句就是用来中断代码的执行的,也就是说,配合 next() 方法,每次只会执行一个 yield 语句。

console.log('a');
setTimeout(() => {
    console.log('b');
}, 0);
console.log('c');
Promise.resolve().then(() => {
    console.log('d');
})
.then(() => {
    console.log('e');
});

console.log('f');
//=> acfdeb
macrotask|microtask
上一篇下一篇

猜你喜欢

热点阅读