zoukankan      html  css  js  c++  java
  • ES6高级技巧(五)

    Set

    由于Set结构没有键名,只有键值所有keys方法和values方法的行为完全一致

    let a=new Set([1,2,3,4])
                 //a.keys()    a.values() 或者直接用of遍历
    for (let item of a) {
        console.log(item)
    }
    /*
    * 1,2,3,4
    * */
    

    forEach()

    let a = new Set([1, 2, 3, 4])
    let b = [];
    a.forEach(v=>b.push(v))
    console.log(b)
    

    数组的map和filter方法也可以间接用于Set

    let set =new Set([1,2,3])
    let set1=new Set([...set].map(v=>v*2))
    console.log(set1)
    //Set { 2, 4, 6 }
    let set2=new Set([...set].filter(v=>v%2==0))
    console.log(set2)
    // Set { 2 }
    

    使用Array.from()

    let set = new Set([1, 2, 3, 4])
    let set1 = Array.from(set, val => val * 2)
    console.log(set1)
    //[ 2, 4, 6, 8 ]
    

    WeakSet

    WeakSet是一种构造函数,可以使用new命令,创建WeakSet数据结构

    weakSet可以接受一个数组或类似数组的对象
    weakSet 的成员只能是对象,而不能是其他类型的值
    add
    has
    delete
    WeakSet没有size属性以及clear()属性,没有办法遍历他的成员
    WeakSet的一个用处,是存储DOM节点,是弱引用
    

    Map

    size()
    constructor
    set()
    get()
    has()
    delete()
    clear()
    遍历方法
    keys()
    values()
    entries()
    forEach()
    Map本身没有map和filter方法,结合数组的方法,实现过滤
    let map1 = new Map()
    map1.set(1, 'a')
    map1.set(2, 'b')
    console.log([...map1])
    //[ [ 1, 'a' ], [ 2, 'b' ] ]
    let b = [...map1].filter(([key, value]) => key <2)
    console.log(b)
    //[ [ 1, 'a' ] ]
    let c=[...map1].map(([key,value])=>key*2)
    console.log(c)
    

    WeakMap

    WeakMap结构与Map结构基本类似,唯一的区别是他只接受对象作为键名,不接受其他类型的值作为键名

    let myElement = document.getElementById('logo')
    let myWeakmap = new WeakMap()
    myWeakmap.set(myElement, { times: 0 })
    myElement.addEventListener('click', function () {
      let login = myWeakmap.get(myElement)
      login.times++
    })
    

    Object.assign

    console.log(Object.assign([1, 2, 3], [4, 5]))
    //把数组视为属性民0,1,2的对象,所以后面的[4,5]覆盖了前面的1,2
    //[4,5,4]
    

    为对象添加方法

    function SomeClass() {
    
    }
    Object.assign(SomeClass.prototype, {
      add(arg1, arg2) {
        return arg1 + arg2
      },
      multi(arg1, arg2) {
        return arg1 - arg2
      }
    })
    let some = new SomeClass()
    console.log(some.add(1, 2))
    console.log(some.multi(1, 2))
    

    合并对象

    let a=[{name:'zhangasn'},{age:12}]
    console.log(Object.assign({}, ...a))
    // { name: 'zhangasn', age: 12 }
    

    Symbol

    const sym = Symbol('foo');
    console.log(sym.description)  //'foo'
    

    作为属性名Symbol

    let mySymbol = Symbol()
    let a = {}
    a[mySymbol] = 'hello';
    console.log(a[mySymbol]) //hello
    
    let b={[mySymbol]:'hello'}
    console.log(b[mySymbol]) //hello
    
    let c=Object.defineProperty({},mySymbol,{value:'hello'})
    console.log(c[mySymbol])//hello
    

    注意,Symbol值作为对象属性名时,不能用点运算符

    const mySymbol = Symbol()
    const a = {}
    a.mySymbol = 'hello'
    console.log(a['mySymbol']) //"hello"
    a[mySymbol]//这个是访问不到的
    
    const obj = {}
    let a = Symbol('a')
    let b = Symbol('b')
    obj[a] = 'hello'
    obj[b] = 'World'
    let cArr = Reflect.ownKeys(obj)
    for (let item of cArr) {
      console.log(obj[item])
      //hello
      // World
    }
    

    Symbol.for()

    Symbol.for()Symbol() 都会生成新的Symbol,他们的区别是,前者会被登记在全局进行搜索,后者不会

    let s1 = Symbol('foo')
    let s2 = Symbol('foo')
    console.log(s1 === s2)//false
    let s3 = Symbol.for('foo')
    let s4 = Symbol.for('foo')
    console.log(s3 === s4)//true
    

    Symbol.iterator

    对象的Symbol.iterator属性,指向该对象的默认遍历器的方法

    const a = {}
    a[Symbol.iterator] = function* () {
      yield 1;
      yield 2;
      yield 3
    };
    console.log([...a])
    

    判断非空isEmpty

    const isEmpty=val=>val===null||!(Object.keys(val)||val).length
    

    判断一个字符串是否有重复的字符

    //采用桶排序的思想
    const isData = str => {
      let flag = Array.from({ length: 128 }, v => 0)
      for (let i = 0; i < str.length; i++) {
        let c = str.charCodeAt(i)
        if (flag[c] > 0) {
          return false
        } else {
          flag[c]++
        }
      }
      return true
    }
    console.log(isData('abc'))
    

    判断两个字符集是否相同

    const equls = (s1, s2) => {
      const map = new Map();
      for (let i = 0; i < s1.length; i++) {
        if (map.get(s1[i]) == null) {
          map.set(s1[i], 1)
        }
      }
      for (let i = 0; i < s2.length; i++) {
        if (map.get(s2[i]) === null) {
          return false
        }
      }
      return true
    }
    

    判断是否是旋转词

    const joint = (str, s1) => {
      let a = ''
      let b = [];
      for (let i = 0; i < str.length; i++) {
        if (i == 0) {
          a = str.slice(i)
        } else {
          a = str.slice(i) + str.slice(0, i)
        }
        b.push(a)
      }
      return b.indexOf(s1) > -1 ? true : false
    }
    

    String

    String.prototype.charAt(index)     0<=index<=length-1   返回特定位置的字符
    
    String.prototype.charCodeAt(index)                      返回给定的字符的Unicode值
    
    String.prototype.concat()                               连接两个字符串文本,返回新的字符串
    
    String.prototype.includes()       判断字符串是否包含                      
    
    endsWith()  判断当前字符串是否是以另外一个给定的子字符串'结尾'  Boolean
    startsWith()                                          '开头' Boolean
    
    String.localeCompare()       'abcsbda'.split('').sort((a, b) => a.localeCompare(b))
    
    String.prototype.padEnd()       两个参数,第一个数字符串的最大长度,第一个参数是添加的字符串,长度不能超过max.length
    
    repeat()    重复的次数
    replace()    替换
    slice()  
    

    比较

    类型 运算规则
    两个值类型进行比较 直接比较数据在序列中的大小
    值类型与引用类型比较 将引用类型的数据转换为与值类型数据相同的数据
    两个引用类型比较 无意义,总是返回false
    console.log('b' > 'a')  //true
    

    for--of的妙用

    let arr = {
      name: 'zhangsan',
      age: 12,
      aa: 'cc'
    }
    for (let [key, value] of Object.entries(arr)) {
      console.log(key + '===' + value)
    }
    

    对象与数组互转

    给每个订单的对账情况加上状态样式(successwarningdanger

    // 状态码说明: 100->对账成功、101->对账中、102->审核中、103->对账失败、104->取消对账
    // 规定有如下样式映射表: 
    const style2StatusMap = {
      success: [100],
      warning: [101,102],
      danger: [103,104]
    }
    //结果
    const status2styleMap = {
      100: 'success',
      101: 'warning',
      102: 'warning',
      103: 'danger',
      104: 'danger'
    }
    
    const status = obj =>
      Object.entries(obj)
        .reduce((acc, val, i, array) => {
          val[1].map(item => {
            acc[item] = array[i][0]
          })
          return acc
        }, {})
    

    保镖模式

    思考无效/边缘情况以及处理的情况

    避免意外和不必要的代码

    遵循自上而下的方法:

    无效情况->小案例->预期案例

    function transformData(rawData) {
      // 检查没有数据的情况
      if (!rawData) {
        return [];
      }
      // 具体检查的情况
      if (rawData.length == 1) {
        return [];
      }
      // 具体代码
      return rawData.map((item) => item);
    }
    

    不用switch

    const contentTypes = {
      post: () => console.log("creating a post..."),
      video: () => console.log("creatinga  video..."),
      default: () => console.log('unrecognized content type')
    };
    
    const createType =(item)=> contentTypes[item] || contentTypes['default'];
    createType('post')()
    

    CSS篇

    auto 和height:auto

    width,height的默认值都是auto

    对于块级元素,auto 自动撑满一行

    对于内联元素,auto 则呈现出包裹性,既由子元素的宽度决定

    无论内联元素还是会计元素,height:auto 都是呈现包裹性,即高度由子级元素撑开。但是父元素设置height: auto会导致子元素height: 100%百分比失效。

    css的属性非常有意思,正常流下,如果块级元素的width是个固定值,marginauto,则margin会撑满剩下的空间;如果margin是固定值,widthauto,则width会撑满剩下的空间。这就是流体布局的根本所在。

    margin:auto 水平垂直居中

    <div class="g-container">
        <div class="g-box"></div>
    </div>
    
    .g-container {
        display: flex;
    }
    
    .g-box {
        margin: auto;
    }
    

    上面的 display: flex 替换成 display: inline-flex | grid | inline-grid 也是可以的。

    实现justify-content: space-between

     <div class="ddd">
          <div class="ccc"></div>
          <div class="ccc"></div>
     </div>
    <style>
    .ddd{
       900px;
      height: 500px;
      border:1px solid #2c3e50;
      display:flex;
      /*justify-content: space-between;*/
      .ccc{
         100px;
        height: 100px;
        background-color: darkblue;
        margin:0 auto;
      }
      .ccc:first-child{
        margin-right: 0;
      }
      .ccc:last-child{
        margin-left:0;
      }
    }
    </style>
    

    实现space-around

    .ddd{
       900px;
      height: 500px;
      border:1px solid #2c3e50;
      display:flex;
      /*justify-content: space-around;*/
      .ccc{
         100px;
        height: 100px;
        background-color: darkblue;
        margin:0 auto;
      }
    }
    

    单个元素右浮动

      <div class="ddd">
          <div class="ccc"></div>
          <div class="ccc"></div>
          <div class="ccc"></div>
        </div>
    .ddd{
       900px;
      height: 500px;
      border:1px solid #2c3e50;
      display:flex;
      .ccc{
         100px;
        height: 100px;
        background-color: darkblue;
      }
      .ccc:last-child{
        margin-left:auto;
      }
    }
    

    此时auto 的计算值就是水平方向上容器排列所有li之后的剩余空间

    两个右浮动

      <div class="ddd">
          <div class="ccc"></div>
          <div class="ccc"></div>
          <div class="ccc aaa"></div>
       <div class="ccc"></div>
        </div>
    
    .ddd{
       900px;
      height: 500px;
      border:1px solid #2c3e50;
      display:flex;
      .ccc{
         100px;
        height: 100px;
        background-color: darkblue;
      }
      .aaa{
        margin-left:auto;
      }
    }
    

    垂直方向居中

    父  {
           display: flex;
        flex-direction:column; 
    }
    
    子{
         margin:auto 0;
    }
    

    例如

    <div class="g-container">
          <p>这是第一行文案</p>
          <p>这是第二行文案</p>
          <p class="aaa">1、剩余多行文案需要垂直居中剩余空间</p>
          <p class="aaa">2、剩余多行文案需要垂直居中剩余空间</p>
          <p>这是最后一行文案</p>
     </div>
    .g-container {
         600px;
        height: 600px;
        border:2px solid #2c3e50;
        display: flex;
        flex-direction:column;
      }
    
      .aaa{
        margin:auto 0;
      }
    

    css 权重

    权重 选择器
    10000 !important(!important并不是选择器,但是权重却是最高的)
    1000 内联样式:style=""
    100 ID选择器:#idName{...}
    10 类、伪类、属性选择器:.className{...} / :hover{...} / [type="text"] ={...}
    1 标签、伪元素选择器:div{...} / :after{...}
    0 通用选择器(*)、子选择器(>)、相邻选择器(+)、同胞选择器(~)
    body#god div.dad span.son { 200px;}
    body#god span#test { 250px;}
    
    (body+div+span=3) + (#god+.dad+.son=120) = 123
    (body+span=2) + (#god+#test=200) = 202
    

    content

    css中的content属性主要用伪元素:after,:before中,其他一般不用

    padding

    注意点

    line-height属性是不作用于padding

    background-clip 设置元素的背景,是否延伸到边框下面

    //三道杠
     .icon1{
       box-sizing:border-box;
        20px;
       height: 30px;
       border-top:2px solid #2c3e50;
       border-bottom:2px solid #2c3e50;
       padding:2px 0;
       background-color: #2c3e50;
       background-clip:content-box;//内容裁剪
     }
    //圆环
    .icon1{
       box-sizing:border-box;
        20px;
       height: 20px;
       border:2px solid #2c3e50;
       padding:4px;
       border-radius:50%;
       background-color: #2c3e50;
       background-clip:content-box;//内容裁剪
     }
    

    margin

    1. 作为外边距,margin属性并不会参与盒子宽度的计算,但是通过设置margin为负值,会改变水平方向的尺寸
      <div class="aaa">
                <div class="bbb"></div>
      </div>
       .aaa {
             500px;
            height: 500px;
            background-color: lightblue;
            margin-left: 500px;
        }
        .bbb {
            /* 100px;别设置宽度*/
            height: 200px;
            background-color: magenta;
            margin-left:-200px;
        }
    

    如果元素设置宽度,或者元素设置了float:left /position:absolute 这样的属性改变了流体布局,那么margin为负就不能改变元素的宽度

    1. 块级元素垂直方向会发生margin合并
    • 相邻兄弟之间margin 合并
    • 父元素margin-top和子元素margin-top ,父元素margin-bottom 和子元素margin-bottom
    • 空块级元素自身的margin-topmargin-bottom合并

    阻止margin合并

    • 把元素放到bfc中(bfc:格式化上下文(浮动,定位,display:inline-block))
    • 设置borderpadding 阻隔margin
    • 给父亲设置内联元素(如文字)阻隔
    • 可以给父元素设置overflow:hidden是利用bfc的特性阻止子元素的margin 和父元素合并,换成其他bfc特性,或者设置1px的border/padding都可以达到效果

    line-heightvertical-align

    • line-height定义的就是两基线之间的距离
    • vertical-align 的默认值就是基线,基线的定义就是字母x的下边缘
    • vertical-align:middle 就是中线对齐

    vertical-align属性起作用的前提必须是作用在内联元素上 ,如果给元素设置float:left 或者position:absolute ,则其vertical-align 属性不能生效,因为这时元素的display计算值为block

    说实话,我用vertical-align

    calc(计算属性)

    margin-left:calc(50%-45px);

  • 相关阅读:
    批处理+7zip解压用纯数字加密的压缩包zip
    golang 读取 chrome保存的网站账号信息
    c++实现"扫描检测硬件改动"
    c++获取磁盘句柄
    golang设置title并获取窗口句柄
    golang获取文件的md5
    golang获取u盘序列号(通过读取注册表实现)
    golang从文件按行读取并输出
    golang cgo注意事项
    python调用远程chromedriver.exe、selenium抓包方法
  • 原文地址:https://www.cnblogs.com/fangdongdemao/p/11263140.html
Copyright © 2011-2022 走看看