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}

 

posted @ 2017-04-01 19:10  吃草的虾米  阅读(150)  评论(0编辑  收藏  举报