zoukankan      html  css  js  c++  java
  • ES6学习笔记

    模块和组件的区别:

    模块是语言层面的,在前面领域我们说的module一般都是指JavaScript module,往往表现为一个单独的js文件,对外暴露一些属性或方法。前端组件则更多是业务层面的概念,可以看成一个可独立使用的功能实现,往往表现为一个UI部件(并不绝对),比如一个下拉菜单、一个富文本编辑器或一个路由系统。一个组件包含它所有资源,包括逻辑(JavaScript) 样式(css) 模块(HTML/template),甚至图片与字体。因而,一个组件有时仅仅是一个JavaScript模块,而更多时候不仅是一个JavaScript模块。前端的组件化方案都不可避免的要以JavaScript的模块方案为基础。

    语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。

    1.箭头函数

    箭头函数:input.map(item=>item+1);

    普通函数:

      input.map(function(item){

        return item + 1;

      })

    2.babel转码(所有babel工具和模块的使用,都必须先写好.babelrc)

      a.presets字段设定转码规则(官方规则集,按需安装)

        #最新的转码规则:npm install --save-dev babel-preset-latest

        #react转码规则:label-preset-react

        #不同阶段语法提案的转码规则(选装一个)

          1.babel-preset-stage-0

          1.babel-preset-stage-1

          3.babel-preset-stage-2

          4.babel-preset-stage-3

      b.命令行转码babel-cli(安装--global babel-cli)

        用法:1.转码结果输出到标准输出:babel example.js

           2.转码结果写入一个文件(--out-file或-o参数指定输出文件):babel example.js -o compiled.js

           3.整个目录转码(--out-dir或-d参数指定输出目录):babel src --out-dir lib

           4.-s参数生成 source map文件:babel src -d lib -s

      更多关于转码的方法可自行找文档。

    3.ES6新增let命令,用来声明变量,它类似于var,但是它只在let命令所在的代码块内有效

      a.let必须先声明再使用,不然会抛出referenceError的错   

      b.ES6明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

      c.不能在相同的作用域里起重复的变量名,就算跟形参的名字相同也不行.在不同的作用域里可以起相同的名字

      d.ES6的块级作用域:一是为了解决内层变量可能会覆盖外层变量的问题,二是为了用来计数的循环变量泄漏为全局变量

      e.ES6允许块级作用域的任意嵌套例子{{{{let cc="bb"}}}}

      f.do表达式:使块级作用域可以变为表达式,也就是说可以返回值。例子:

        let x = do {let t = f(); t * t + 1}

    4.const声明一个只读的常量。一旦声明,常量的值就不能改变。const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。只声明不赋值会报错。const和let相同,只在声明所在的块级作用域内有效。必须先声明后使用。在同一作用域内,变量名不可以重复。

      注意:const并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。所以在声明对象和数组时要想让它不得改动需要加Object.freeze({});下面是将对象本身和对象属性都冻结的例子:

      var constantize = (obj) => {

        Object.freeze(obj);

        Object.keys(obj).forEach((key,i) => {

          if(typeof obj[key] === 'object'){

            constantize(obj[key])

          }

        })

      }

    5.ES6六种声明变量的方法:var , function , let , const , import , class

    6.数组的解构赋值(只要某种数据结构具有iterator接口,都可以采用数组形式的解构赋值)

    let[a, b, c] = [1,2,3]

    let[foo,[[bar],baz]] = [1,[[2],3]] ; foo//1,bar//2,baz//3

    let[,,third] = ['foo','bar','baz'];third//baz

    let[x,,y] = [1,2,3];x//1,y//3

    let[head,...tail] = [1,2,3,4];head//1 ,tail //[2,3,4]

    let[x,y,...z] = ['a'];x//a,y//undefined,z//[]

    let[x,y] = [1,2,3];x//1,y//2

    let[a,[b],d] = [1,[2,3],4] ;a//1,b//2,d//4

    let[x,y,z] = new Set(['a','b','c'])

    //默认值

    let[foo = true] = [];foo//true

    let[x,y = 'b'] = ['a']; //x='a',y='b'

    let[x,y = 'b'] = ['a',undefined]; //x='a',y='b'

    let[x = 1] = [null];x//null  因为null不严格等于undefined,所以默认值就不会生效

    //如果默认值是一个表达式,那么这个表达式是惰性求值,只有用到的时候才会求值。下面例子因为x能取到值所以f根本不会执行。

    function f(){console.log("aaa")}; let[x = f()] = [1];

    //默认值可以引用解构赋值的其他变量,但该变量必须已经声明

    let[x =1, y = x] = [];//x=1,y=1

    let[x = 1,y = x] = [2];//x=2,y=2

    let[x = 1,y = x] = [1,2];//x=1;y=2

    let[x = y,y = 1] = [] //referenceError

    7.对象的解构赋值(默认值得用法和数组相同)

    let{bar,foo} = {foo:"aaa",bar:"bbbb"};foo //'aaa',bar//'bbb'

    let{baz} = {foo:'aaa'}; baz //undefined

    let{foo:baz} = {foo:'a',bar:'b'};baz//'a'

    let obj = {first:'a',last:'b'};let{first:f,last:l} = obj; f//'a',l//'b'

    let foo;({foo} = {foo:1})//圆括号是必须的,因为解析器会将起首的大括号,理解成一个代码块,而不是赋值语句。

     let{log,sin,cos} = Math;//代码将Math对象的对应,正弦,余弦三个方法,赋值到对象的变量上,使用起来就会方便很多。

    8.字符串的解构赋值

    const[a,b,c]='hhm';a//'h',b//'h',c//'m'

    let{length:len} = 'hell'; len //5

    9.数组和布尔值的解构赋值(如果等号右边是数值或布尔值,则会先转为对象)

    undefined,null无法转为对象,所以对它们进行解构赋值时就会报错

    10.函数参数的解构赋值

    function add([x,y]){return x+y} add([1,2]) //3

    [[1,2],[3,4]].map(([a,b]) => a+b);//[3,7]

    11.可以使用括号的情况:是赋值语句,不是声明语句;括号不属于模式的一部分

    12.字符串的遍历器接口for(let a of 'foo'){console.log(a)}

    13.at()方法可以识别unicode编号大于0xFFFF的字符

    14.normalize()方法,用来将字符的不同表示方法统一为同样的形式

    15.

      includes():返回布尔值,表示是否找到了参数字符串

      startsWith():返回布尔值,表示参数字符串是否在原字符串的头部

      endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部

     例子:三个方法都支持第二个参数,但是endswith的行为与其他两个不同它针对前n个字符,而其他两个是针对从第n个位置直到字符串结束

      var s = "Hello world"

      s.startsWith("world");s.endsWith("Hello",5);s.includes("Hello",6)

    16.repeat()表示将原字符串重复n次 'x'.repeat(3) //"xxx"

    17.padStart(),padEnd()头尾补全。'x'.padStart(4,'ab');//abax; 'x'.padEnd(5,'n');//xnnnn

    18.模板字符串的新用法反引号(‘)标识。它可以当做普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量,使用时需要加转义

    $("#a").append(‘adsdf<b>${basket.count}</b>‘)

    使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出中,如果不想保留用trim()方法消除它

     $('#list').html(`
    
      <ul>
    
      <li>first</li>
      <li>second</li>
    </ul>
    `.trim());

    19.Generator:是异步编程的解决方案。调用generator函数时,返回一个遍历器对象,代表generator函数的内部指针。以后每次调用遍历器对象的next方法,会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表达是否遍历结束。它与传统的函数区别在于:

      1.function关键字和函数名之间有一个星号(星号只要在中间无论有无空格靠近哪边都可以通过)

      2.函数体内部使用yield表达式,定义不同的内部状态。只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield表达式就是暂停标志。如果没有yield就会一直运行到函数结束,直到return语句为止。如果没有return语句,则返回的对象value属性值为undefined。任何数据结构只要有Iterator接口,就可以被yield*遍历。

    generator方法的定义:
    
    function* testGenerator(){
       yield 'hello';  
       yield 'world';
       return 'ending';  
    }
    调用:
    
    var hw = testGenerator();
          hw.next()  //{value:'hello',done:false}
          hw.next() //{value:'world',done:false}
          hw.next() //{value:'ending',done:true}
          hw.next() //{value:undefined,done:true} 

    //yield表达式如果用在另一个表达式之中,必须放在圆括号里
    function* demo(){
    console.log('Hello'+(yield))
    }

    //yield表达式用作函数参数或放在赋值表达式的右边,可以不加括号
    function* demo(){
    foo(yield 'a' ,yield 'b')
     let input = yield 
    }

    //如果yield后面跟的是遍历器对象,那么yield后面加*号
    function* inner(){
      yield 'hello';
    }
    function* outer(){
      yield 'open'
    yield* inner()
    }

     20.promise:Promise对象是一个构造函数,用来生成Promise实例。是异步编程的一种解决方案。简单说就是个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,promise是一个对象,从它可以获取异步操作的消息。有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免层层嵌套的回调函数。此外,promise对象提供统一的接口,使得控制异步操作更加容易

      promise对象的特点:

    • 对象状态不受外界影响。promise对象代表一个异步操作,有三种状态:Pending(进行中)、Fulfiled(已成功)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是promise(承诺)这个名字的由来,其它手段无法改变。
    • 一旦状态改变,就不会再变,任何时候都可以得到这个结果。promise对象的状态改变,只有两种可能:从Pending变为Fulfiled和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为Resolved(已定型)如果改变已发生了,你再对promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。  

      promise对象的缺点:

    • 一旦新建它就会立即执行,无法中途取消。
    • 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部
    • 当处于Pending(进行中)状态时,无法得知目前进展到哪一个阶段了。

           promise的then方法:返回一个新的promise实例(注意,不是原来的那个promise实例)因此可以采用链式写法,即then方法后面再调用另一个then方法。采用链式的then,可以指定一组按照次序调用的回调函数。这时,前一个回调函数,有可能返回的还是一个promise对象(即有异步操作),这时后一个回调函数,就会等待该promise对象的状态发生变化,才会被调用

      promise的promise.prototype.catch():它是.then(null,rejection) 的别名,用于指定发生错误时的回调函数。它可以捕获异步操作抛出的错误,还有运行中抛出的错误。如果状态已变成成功(Fulfiled)再抛出异常是不会被捕获到的。promise对象的错误具有"冒泡"性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。

      promise.all方法用于将多个Promise实例,包装成一个新的promise实例。(它接收的参数可以不是数组,但必须具有Iterator接口, 且返回的每个成员都是Promise实例。传递的参数只要有一个失败就会返回失败。如果作为参数的Promise实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法)

      Promise.race()方法跟all()方法一样,会将多个Promise实例,包装成一个新的Promise实例。

      Promise.resolve()方法可以将现有对象转为Promise对象。

      Promise.try()方法能使同步的方法同步执行异步的方法异步执行

     21. Object.assign:合并对象

    Object.assign({},{1,2},{3})  //{1,2,3}
  • 相关阅读:
    类的加载机制与反射 笔记
    json
    人人都是产品经理 笔记
    java IO
    jcrop+jquery+javaweb 实现头像裁剪、上传
    C++学习-3
    C++学习-2
    C++学习-1
    Django高级部分
    Django---模板
  • 原文地址:https://www.cnblogs.com/cxdxm/p/6657242.html
Copyright © 2011-2022 走看看