ES6新语法快速入门学习教程
2017-09-30 16:23
633 查看
什么是ES6?
ECMAScript6(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了。
ECMAScript和JavaScript到底是什么关系?很多初学者会感到困惑,简单来说,ECMAScript是JavaScript语言的国际标准,JavaScript是ECMAScript的实现。
1996年11月,JavaScript的创造者Netscape公司,决定将JavaScript提交给国际标准化组织ECMA,希望这种语言能够成为国际标准。次年,ECMA发布262号标准文件(ECMA-262)的第一版,规定了浏览器脚本语言的标准,并将这种语言称为ECMAScript。这个版本就是ECMAScript
1.0版。
ES6的目标,是使得JavaScript语言可以用来编写大型的复杂的应用程序,成为企业级开发语言。
支持ES6的浏览器:
虽说ES6已经作为新一代标准发布了,但是各大浏览器对新功能实现支持的还需要一段时间,那么我们怎么知道自己使用的浏览器是否支持ES6的相应功能呢?
不用紧张,对ES6的支持可以查看kangax.github.io/es5-compat-table/es6/,在这里可以清晰的了解到不同版本的浏览器对ES6功能的支持情况。随着时间的推移,支持度已经越来越高了,ES6的大部分特性都实现了。
如果你想现在就在浏览器使用ES6的特性,还可以通过引用兼容包的方式提前尝尝鲜。https://github.com/paulmillr/es6-shim
环境支持:babel
直接插入网页
Traceur允许将ES6代码直接插入网页。首先,必须在网页头部加载Traceur库文件。
注意,script标签的type属性的值是module(或者traceur),而不是text/javascript。这是Traceur编译器识别ES6代码的标识,编译器会自动将所有type=module的代码编译为ES5,然后再交给浏览器执行。
let
let是ES6中新增关键字。
它的作用类似于var,用来声明变量,但是所声明的变量,只在let命令所在的代码块内有效。
体会下let和var的作用域范围:
const命令
const声明的是常量,一旦声明,值将是不可变的。
const也具有块级作用域
const不可重复声明
是否包含字符串三种新方法
传统上,JavaScript只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6又提供了三种新方法。
includes():返回布尔值,表示是否找到了参数字符串。
startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。
这三个方法都支持第二个参数,表示开始搜索的位置。
上面代码表示,使用第二个参数n时,endsWith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束。
repeat()原字符串重复
repeat()返回一个新字符串,表示将原字符串重复n次。
模板字符串
模板字符串提供了3个有意思的特性。
模板字符中,支持字符串插值:
模板字符串可以包含多行:
Array.from()
下面是一个类似数组的对象,
Array.from()还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理。
Array.of()
Array.of方法用于将一组值,转换为数组。
数组实例的find()和findIndex()
数组实例的
数组实例的findIndex方法,用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。
fill()填充数组(了解)
fill()使用给定值,填充一个数组。
上面代码表明,fill方法用于空数组的初始化非常方便。数组中已有的元素,会被全部抹去。
fill()还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。
entries()keys()values()-ES6提供三个新的方法
ES6提供三个新的方法:
entries()
keys()
values()
用于遍历数组。它们都返回一个遍历器,可以用for...of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。
Es6对象的扩展
属性的简洁表示法
ES6允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
上面代码表明,ES6允许在对象之中,直接写变量。这时,属性名为变量名,
属性值为变量的值。下面是另一个例子。
方法的简洁表示法
属性结合方法简写的例子:
属性名表达式
JavaScript语言定义对象的属性,有两种方法
上面代码的方法一是直接用标识符作为属性名,方法二是用表达式作为属性名,这时要将表达式放在方括号之内。
如果使用字面量方式定义对象(使用大括号),在ES5中只能使用方法一(标识符)定义属性。
ES6允许字面量定义对象时,用方法二(表达式)作为对象的属性名,即把表达式放在方括号内。
表达式还可以用于定义方法名。
Object.is()比较两个值是否严格相等
Object.is()用来比较两个值是否严格相等。它与严格比较运算符(===)的行为基本一致,不同之处只有两个:一是+0不等于-0,二是NaN等于自身。
Object.assign()源对象的所有可枚举属性,复制到目标对象
Object.assign方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target)。它至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象。只要有一个参数不是对象,就会抛出TypeError错误。
注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
vartarget={a:1,b:1};
varsource1={b:2,c:2};
varsource2={c:3};
Object.assign(target,source1,source2);
target//{a:1,b:2,c:3}
(1)为对象添加属性
(2)为对象添加方法
(3)克隆对象
(4)合并多个对象
ES6函数的扩展
默认参数
现在可以在定义函数的时候指定参数的默认值了,而不用像以前那样通过逻辑或操作符来达到目的了。。
rest参数(形式为“...变量名”)可以称为不定参数
rest参数(形式为“...变量名”)可以称为不定参数,用于获取函数的多余参数,这样就不需要使用arguments对象了。
rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
不定参数的格式是三个句点后跟代表所有不定参数的变量名。比如以上示例中,...values代表了所有传入add函数的参数。
扩展运算符
扩展运算符(spread)是三个点(...)。它好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列。该运算符主要用于函数调用。
它允许传递数组或者类数组直接做为函数的参数而不用通过apply。
箭头函数
箭头函数是使用=>语法的函数简写形式。这在语法上与C#、Java8和CoffeeScript的相关特性非常相似。
函数绑定
函数绑定运算符是并排的两个双引号(::),双引号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。
ES6SETWeakSet
SET基本用法
数据结构Set类似于数组,但是成员的值都是唯一的,没有重复的值。
Set函数可以接受一个数组作为参数,用来初始化
SET实例属性和方法
Set实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。下面先介绍四个操作方法。
·add(value):添加某个值,返回Set结构本身。
·delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
·has(value):返回一个布尔值,表示该值是否为Set的成员。
·clear():清除所有成员,没有返回值。
下面是一个对比,看看在判断是否包括一个键上面,
SET遍历操作
Set结构的实例有四个遍历方法,可以用于遍历成员。
keys():返回一个键名的遍历器
values():返回一个键值的遍历器
entries():返回一个键值对的遍历器
forEach():使用回调函数遍历每个成员
由于Set结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。
WeakSet和Set一样都不存储重复的元素,但有一些不同点。
WeakSet的成员只能是对象,而不能是其他类型的值。
WeakSet结构有以下三个方法。
WeakSet.prototype.add(value):向WeakSet实例添加一个新成员。
WeakSet.prototype.delete(value):清除WeakSet实例的指定成员。
WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在
ES6函数的map
Map结构的目的和基本用法
Map是一个“超对象”,其
key除了可以是String
类型之外,还可以为其他类型(如:对象)
他的方法和Set
差不多:
size:返回成员总数。
set(key,value):设置一个键值对。
get(key):读取一个键。
has(key):返回一个布尔值,表示某个键是否在Map数据结构中。
delete(key):删除某个键。
clear():清除所有成员。
keys():返回键名的遍历器。
values():返回键值的遍历器。
entries():返回所有成员的遍历器。
实例的属性和操作方法
Map结构的实例有以下属性和操作方法。
size:返回成员总数。
set(key,value):设置key所对应的键值,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就新生成该键。
get(key):读取key对应的键值,如果找不到key,返回undefined。
has(key):返回一个布尔值,表示某个键是否在Map数据结构中。
delete(key):删除某个键,返回true。如果删除失败,返回false。
clear():清除所有成员,没有返回值。
set()方法返回的是Map本身,因此可以采用链式写法。
下面是has()和delete()的例子。
下面是size属性和clear方法的例子。
遍历方法
Map原生提供三个遍历器。
keys():返回键名的遍历器。
values():返回键值的遍历器。
entries():返回所有成员的遍历器。
使用示例:
Map结构转为数组结构,比较快速的方法是结合使用扩展运算符(...)。
此外,Map还有一个forEach方法,与数组的forEach方法类似,也可以实现遍历。
WeakMap
WeakMap结构与Map结构基本类似,唯一的区别是它只接受对象作为键名(null除外),不接受原始类型的值作为键名,而且键名所指向的对象,不计入垃圾回收机制。set()和get()分别用来添加数据和获取数据:
WeakMap与Map在API上的区别主要是两个:
·一是没有遍历操作(即没有key()、values()和entries()方法),也没有size属性;
·二是无法清空,即不支持clear方法。这与WeakMap的键不被计入引用、被垃圾回收机制忽略有关。
因此,WeakMap只有四个方法可用:get()、set()、has()、delete()。
ES6Class
ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。
上面代码定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。
constructor方法
constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。
=newPoint(2,3);
2.Point.name
//"Point"
Class的继承
Class之间可以通过extends关键字,实现继承。
子类会继承父类的属性和方法。
上面代码中,子类的constructor方法没有调用super之前,就使用this关键字,结果报错,而放在super方法之后就是正确的。
注意:ColorPoint继承了父类Point,但是它的构造函数必须调用super方法。
Class的静态方法
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
上面代码中,Foo类的classMethod方法前有static关键字,表明该方法是一个静态方法,可以直接在Foo类上调用(Foo.classMethod()),而不是在Foo类的实例上调用。如果在实例上调用静态方法,会抛出一个错误,表示不存在该方法。
父类的静态方法,可以被子类继承。
上面代码中,父类Foo有一个静态方法,子类Bar可以调用这个方法。
静态方法也是可以从super对象上调用的。
ES6模块
export命令
模块功能主要由两个命令构成:export和import。
export命令用于用户自定义模块,规定对外接口;
import命令用于输入其他模块提供的功能,同时创造命名空间(namespace),防止函数名冲突。
ES6允许将独立的JS文件作为模块,允许一个JavaScript脚本文件调用另一个脚本文件。
现有profile.js文件,保存了用户信息。ES6将其视为一个模块,里面用export命令对外部输出了三个变量。
import命令就用于加载profile.js文件,并从中输入变量。import命令接受一个对象(用大括号表示),里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同。
如果想为输入的变量重新取一个名字,import语句中要使用as关键字,将输入的变量重命名。
exportdefault命令
为加载模块指定默认输出,使用exportdefault命令。
上面代码是一个模块文件export-default.js,它的默认输出是一个函数。
其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。
上面代码的import命令,可以用任意名称指向export-default.js输出的方法。需要注意的是,这时import命令后面,不使用大括号。
ECMAScript6(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了。
ECMAScript和JavaScript到底是什么关系?很多初学者会感到困惑,简单来说,ECMAScript是JavaScript语言的国际标准,JavaScript是ECMAScript的实现。
1996年11月,JavaScript的创造者Netscape公司,决定将JavaScript提交给国际标准化组织ECMA,希望这种语言能够成为国际标准。次年,ECMA发布262号标准文件(ECMA-262)的第一版,规定了浏览器脚本语言的标准,并将这种语言称为ECMAScript。这个版本就是ECMAScript
1.0版。
ES6的目标,是使得JavaScript语言可以用来编写大型的复杂的应用程序,成为企业级开发语言。
支持ES6的浏览器:
虽说ES6已经作为新一代标准发布了,但是各大浏览器对新功能实现支持的还需要一段时间,那么我们怎么知道自己使用的浏览器是否支持ES6的相应功能呢?
不用紧张,对ES6的支持可以查看kangax.github.io/es5-compat-table/es6/,在这里可以清晰的了解到不同版本的浏览器对ES6功能的支持情况。随着时间的推移,支持度已经越来越高了,ES6的大部分特性都实现了。
如果你想现在就在浏览器使用ES6的特性,还可以通过引用兼容包的方式提前尝尝鲜。
环境支持:babel
直接插入网页
Traceur允许将ES6代码直接插入网页。首先,必须在网页头部加载Traceur库文件。
<!--加载Traceur编译器--> <scriptsrc="http://google.github.io/traceur-compiler/bin/traceur.js" type="text/javascript"></script> <!--将Traceur编译器用于网页--> <scripttype="text/javascript"> newtraceur.WebPageTranscoder(document.location.href).run(); </script> <!--打开实验选项,否则有些特性可能编译不成功--> <script> traceur.options.experimental=true; </script> <scripttype="module"> classCalc{ constructor(){ console.log('Calcconstructor'); } add(a,b){ returna+b; } } varc=newCalc(); console.log(c.add(4,5)); </script> |
let
let是ES6中新增关键字。
它的作用类似于var,用来声明变量,但是所声明的变量,只在let命令所在的代码块内有效。
if(true){ vara=1; letb=2; } document.write(a); document.write(b);//报错:ReferenceError:bisnotdefined |
functionf1(){ 24e68 vara=8; letn=5; if(true){ letn=10; vara=20 } document.write(n);//5 document.write(a);//20 } f1(); |
const声明的是常量,一旦声明,值将是不可变的。
constPI=3.1415; console.log(PI); PI=3; console.log(PI); |
if(true){ constmax=5; } document.write(max);//ReferenceError常量MAX在此处不可得 |
varmessage="Hello!"; letage=25; //以下两行都会报错 constmessage="Goodbye!"; constage=30; |
传统上,JavaScript只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6又提供了三种新方法。
includes():返回布尔值,表示是否找到了参数字符串。
startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。
varstr="Helloworld!"; str.startsWith("Hello")//true str.endsWith("!")//true str.includes("o")//true |
varstr="Helloworld!"; str.startsWith("world",6)//true str.endsWith("Hello",5)//true str.includes("Hello",6)//false |
repeat()原字符串重复
repeat()返回一个新字符串,表示将原字符串重复n次。
varstr="x"; str.repeat(3)//"xxx" varstr1="hello"; str1.repeat(2)//"hellohello" |
模板字符串提供了3个有意思的特性。
模板字符中,支持字符串插值:
letfirst='我叫xxx'; letlast='我是搬砖工'; document.write(`Hello${first}${last}!`);//注意引号 |
letmultiLine=` Thisis astring withmultiple lines`; document.write(multiLine); |
Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-likeobject)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map)。
下面是一个类似数组的对象,
Array.from将它转为真正的数组。
letarray=Array.from({0:"a",1:"b",2:"c",length:3}); document.write(array);//["a","b","c"] |
letarrayLike={ '0':'a', '1':'b', '2':'c', length:3 }; //ES5的写法这句话相当于Array.prototype.slice.call(arrayLike) //目的是将arrayLike对象的数组提出来转化为数组,arrayLike本身并不是数组而是对象 vararr1=[].slice.call(arrayLike);//['a','b','c'] console.log(arr1); //ES6的写法 letarr2=Array.from(arrayLike);//['a','b','c'] console.log(arr2); |
letarray=[0,1,2,3,4]; letarrNew=Array.from(array,x=>x*x); console.log(arrNew); //等同于 letarrNew=Array.from(array).map(x=>x*x); |
Array.of方法用于将一组值,转换为数组。
Array.of(3,11,8)//[3,11,8] Array.of(3)//[3] Array.of(3).length//1 |
数组实例的
find方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为
true的成员,然后返回该成员。如果没有符合条件的成员,则返回
undefined。
letarray=[1,4,-5,10].find((n)=>n<0); document.write("array:",array); //上面代码找出数组中第一个小于0的成员。 |
//下面代码中find方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。 letarray=[1,5,10,15].find(function(value,index,arr){ returnvalue>9; }) document.write(array);//10 |
letindex=[1,5,10,15].findIndex(function(value,index,arr){ returnvalue>9; }) document.write(index);//2 |
fill()使用给定值,填充一个数组。
letarr=['a','b','c'].fill(7) document.write(arr);//[7,7,7] letnewArr=newArray(3).fill(7) document.write(newArr);//[7,7,7] |
fill()还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。
letnewArr=['a','b','c'].fill(7,1,2) document.write(newArr);//['a',7,'c'] |
entries()keys()values()-ES6提供三个新的方法
ES6提供三个新的方法:
entries()
keys()
values()
用于遍历数组。它们都返回一个遍历器,可以用for...of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。
for(letindexof['a','b'].keys()){ document.write(index); } //0 //1 for(letelemof['a','b'].values()){ document.write(elem); } //'a' //'b' for(let[index,elem]of['a','b'].entries()){ document.write(index,elem); } //0"a" //1"b" |
属性的简洁表示法
ES6允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
varfoo='bar'; varbaz={foo}; baz//{foo:"bar"} //等同于 varbaz={foo:foo}; |
属性值为变量的值。下面是另一个例子。
functionf(x,y){ return{x,y}; } // 等同于 functionf(x,y){ return{x:x,y:y}; } f(1,2)//Object{x:1,y:2} |
varo={ method(){//es6 方法的简写 return"Hello!"; } }; console.log(o); // 等同于 varo={ method:function(){ return"Hello!"; } }; console.log(o); |
varbirth='2000/01/01'; varPerson={ name:'张三', //等同于birth:birth birth, //等同于hello:function()... hello(){console.log('我的名字是',this.name);} }; |
JavaScript语言定义对象的属性,有两种方法
// 方法一 letobj={}; obj.foo=true; // 方法二 obj['a'+'bc']=123; console.log(obj); |
上面代码的方法一是直接用标识符作为属性名,方法二是用表达式作为属性名,这时要将表达式放在方括号之内。
如果使用字面量方式定义对象(使用大括号),在ES5中只能使用方法一(标识符)定义属性。
varobj={ foo:true, abc:123 }; |
letpropKey='foo'; letobj={ [propKey]:true, ['a'+'bc']:123 }; |
letobj={ ['h'+'ello'](){ return'hi'; } }; document.write(obj.hello());//hi |
Object.is()比较两个值是否严格相等
Object.is()用来比较两个值是否严格相等。它与严格比较运算符(===)的行为基本一致,不同之处只有两个:一是+0不等于-0,二是NaN等于自身。
+0===-0//true NaN===NaN//false Object.is(+0,-0)//false Object.is(NaN,NaN)//true |
Object.assign方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target)。它至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象。只要有一个参数不是对象,就会抛出TypeError错误。
vartarget={a:1}; varsource1={b:2}; varsource2={c:3}; Object.assign(target,source1,source2); target//{a:1,b:2,c:3} |
vartarget={a:1,b:1};
varsource1={b:2,c:2};
varsource2={c:3};
Object.assign(target,source1,source2);
target//{a:1,b:2,c:3}
Object.assign方法有很多用处。
(1)为对象添加属性
(2)为对象添加方法
(3)克隆对象
(4)合并多个对象
ES6函数的扩展
默认参数
现在可以在定义函数的时候指定参数的默认值了,而不用像以前那样通过逻辑或操作符来达到目的了。。
//运用ES6的默认参数 functionsayHello(name){ //传统的指定默认参数的方式 varname=name||'qianfeng'; document.write('Hello'+name); } //运用ES6的默认参数 functionsayHello2(name='qianfeng'){ document.write(`Hello${name}`);/*注意引号*/ } sayHello();//输出:Helloqianfeng sayHello('我是代码搬砖工');//输出:Hello我是代码搬砖工 sayHello2();//输出:Hello我是代码搬砖工 sayHello2('我是代码搬砖工');//输出:Hello我是代码搬砖工 |
rest参数(形式为“...变量名”)可以称为不定参数,用于获取函数的多余参数,这样就不需要使用arguments对象了。
rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
functionadd(...values){ letsum=0; for(varvalofvalues){ sum+=val; } returnsum; } add(1,2,3)//6 |
扩展运算符
扩展运算符(spread)是三个点(...)。它好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列。该运算符主要用于函数调用。
它允许传递数组或者类数组直接做为函数的参数而不用通过apply。
varpeople=[' 张三 ',' 李四 ',' 王五 ']; //sayHello 函数本来接收三个单独的参数 people1 , people2 和 people3 functionsayHello(people1,people2,people3){ document.write(`Hello${people1},${people2},${people3}`); } // 但是我们将一个数组以拓展参数的形式传递,它能很好地映射到每个单独的参数 sayHello(...people);// 输出: Hello 张三 , 李四 , 王五 // 而在以前,如果需要传递数组当参数,我们需要使用函数的 apply 方法 sayHello.apply(null,people);// 输出: Hello 张三 , 李四 , 王五 //ES5 [1,2].concat([code]more)[/code] //ES6 [1,2,...[code]more][/code] var[code]arr1=['a','b'];[/code] var[code]arr2=['c'];[/code] var[code]arr3=['d','e'];[/code] //ES5的合并数组 arr1.concat( arr2, arr3);[/code] //['a','b','c','d','e'] //ES6的合并数组 [...[code]arr1,... arr2,... arr3][/code] //['a','b','c','d','e'] |
箭头函数是使用=>语法的函数简写形式。这在语法上与C#、Java8和CoffeeScript的相关特性非常相似。
vararray=[1,2,3]; // 传统写法 array.forEach(function(v,i,a){ document.write(v); }); //ES6 array.forEach(v=>document.write(v)); |
注意:
它们同时支持表达式体和语句体。与(普通的)函数所不同的是,箭头函数和其上下文中的代码共享同一个具有词法作用域的
this
。
varevens=[1,2,3,4,5]; varfives=[]; // 表达式体 varodds=evens.map(v=>v+1); varnums=evens.map((v,i)=>v+i); varpairs=evens.map(v=>({even:v,odd:v+1})); // 语句体 nums.forEach(v=>{ if(v%5===0) fives.push(v); }); document.write(fives); // 具有词法作用域的 this varbob={ _name:"Bob", _friends:["Amy","Bob","Cinne","Dylan","Ellen"], printFriends(){ this._friends.forEach(f=> document.write(this._name+"knows"+f)); } } bob.printFriends(); |
函数绑定运算符是并排的两个双引号(::),双引号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。
letlog=::console.log; //等同于 varlog=console.log.bind(console); foo::bar; //等同于 bar.call(foo); foo::bar(...arguments); i//等同于 bar.apply(foo,arguments); |
ES6SETWeakSet
SET基本用法
数据结构Set类似于数组,但是成员的值都是唯一的,没有重复的值。
vars=newSet(); [2,3,5,4,5,2,2].map(x=>s.add(x)); for(letiofs){ console.log(i); } |
varitems=newSet([1,2,3,4,5,5,5,5]); document.write(items.size);//5 |
Set实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。下面先介绍四个操作方法。
·add(value):添加某个值,返回Set结构本身。
·delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
·has(value):返回一个布尔值,表示该值是否为Set的成员。
·clear():清除所有成员,没有返回值。
s.add(1).add(2).add(2); //注意2被加入了两次 s.size//2 s.has(1)//true s.has(2)//true s.has(3)//false s.delete(2); s.has(2)//false |
Object结构和
Set结构的写法不同。
//对象的写法 varproperties={ 'width':1, 'height':1 }; if(properties[someName]){ //dosomething } //Set的写法 varproperties=newSet(); properties.add('width'); properties.add('height'); if(properties.has(someName)){ //dosomething } |
Set结构的实例有四个遍历方法,可以用于遍历成员。
keys():返回一个键名的遍历器
values():返回一个键值的遍历器
entries():返回一个键值对的遍历器
forEach():使用回调函数遍历每个成员
由于Set结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。
letset=newSet(['red','green','blue']); for(letitemofset.keys()){ document.write(item); } //red //green //blue for(letitemofset.values()){ document.write(item); } //red //green //blue for(letitemofset.entries()){ document.write(item); } //["red","red"] //["green","green"] //["blue","blue"] set.forEach(function(item){ document.write(item); }) |
WeakSet的成员只能是对象,而不能是其他类型的值。
varws=newWeakSet(); ws.add(1) //TypeError:Invalidvalueusedinweakset |
WeakSet.prototype.add(value):向WeakSet实例添加一个新成员。
WeakSet.prototype.delete(value):清除WeakSet实例的指定成员。
WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在
varws=newWeakSet(); varobj={}; varfoo={}; ws.add(window); ws.add(obj); ws.has(window);//true ws.has(foo);//false ws.delete(window); ws.has(window);//false |
Map结构的目的和基本用法
Map是一个“超对象”,其
key除了可以是String
类型之外,还可以为其他类型(如:对象)
varm=newMap(); o={p:"HelloWorld"}; m.set(o,"content") document.write(m.get(o)) //"content" |
差不多:
size:返回成员总数。
set(key,value):设置一个键值对。
get(key):读取一个键。
has(key):返回一个布尔值,表示某个键是否在Map数据结构中。
delete(key):删除某个键。
clear():清除所有成员。
keys():返回键名的遍历器。
values():返回键值的遍历器。
entries():返回所有成员的遍历器。
实例的属性和操作方法
Map结构的实例有以下属性和操作方法。
size:返回成员总数。
set(key,value):设置key所对应的键值,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就新生成该键。
get(key):读取key对应的键值,如果找不到key,返回undefined。
has(key):返回一个布尔值,表示某个键是否在Map数据结构中。
delete(key):删除某个键,返回true。如果删除失败,返回false。
clear():清除所有成员,没有返回值。
set()方法返回的是Map本身,因此可以采用链式写法。
letmap=newMap() .set(1,'a') .set(2,'b') .set(3,'c'); document.write(map); |
varm=newMap(); m.set("edition",6)//键是字符串 m.set(262,"standard")//键是数值 m.set(undefined,"nah")//键是undefined varhello=function(){document.write("hello");} m.set(hello,"HelloES6!")//键是函数 m.has("edition")//true m.has("years")//false m.has(262)//true m.has(undefined)//true m.has(hello)//true m.delete(undefined) m.has(undefined)//false m.get(hello)//HelloES6! m.get("edition")//6 |
letmap=newMap(); map.set('foo',true); map.set('bar',false); map.size//2 map.clear() map.size//0 |
Map原生提供三个遍历器。
keys():返回键名的遍历器。
values():返回键值的遍历器。
entries():返回所有成员的遍历器。
使用示例:
letmap=newMap([ ['F','no'], ['T','yes'], ]); for(letkeyofmap.keys()){ document.write(key); } //"F" //"T" for(letvalueofmap.values()){ document.write(value); } //"no" //"yes" for(letitemofmap.entries()){ document.write(item[0],item[1]); } //"F""no" //"T""yes" //或者 for(let[key,value]ofmap.entries()){ document.write(key,value); } //等同于使用map.entries() for(let[key,value]ofmap){ document.write(key,value); } |
letmap=newMap([ [1,'one'], [2,'two'], [3,'three'], ]); [...map.keys()] //[1,2,3] [...map.values()] //['one','two','three'] [...map.entries()] //[[1,'one'],[2,'two'],[3,'three']] [...map] //[[1,'one'],[2,'two'],[3,'three']] |
map.forEach(function(value,key,map)){ document.write("Key:%s,Value:%s",key,value); }; |
WeakMap结构与Map结构基本类似,唯一的区别是它只接受对象作为键名(null除外),不接受原始类型的值作为键名,而且键名所指向的对象,不计入垃圾回收机制。set()和get()分别用来添加数据和获取数据:
varmap=newWeakMap(), element=document.querySelector(".element"); map.set(element,"Original"); //下面就可以使用了 varvalue=map.get(element); document.write(value);//"Original" |
·一是没有遍历操作(即没有key()、values()和entries()方法),也没有size属性;
·二是无法清空,即不支持clear方法。这与WeakMap的键不被计入引用、被垃圾回收机制忽略有关。
因此,WeakMap只有四个方法可用:get()、set()、has()、delete()。
ES6Class
ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。
//定义类 classPoint{ constructor(x,y){ this.x=x; this.y=y; } toString(){ return'('+this.x+','+this.y+')'; } } |
constructor方法
constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。
实例对象
1.varpoint=newPoint(2,3);
name属性
1.classPoint{}2.Point.name
//"Point"
class表达式
与函数一样,Class也可以使用表达式的形式定义。constMyClass=classMe{ getClassName(){ returnMe.name; } }; varc=newMyClass(); console.log(c.getClassName()); |
Class之间可以通过extends关键字,实现继承。
子类会继承父类的属性和方法。
classPoint{ constructor(x,y){ this.x=x; this.y=y; } } classColorPointextendsPoint{ constructor(x,y,color){ //this.color=color;//ReferenceError super(x,y);// this.color=color;//正确 }/*注意方法之家没有分号*/ getData(){ //console.log('123'); console.log(this.x+'--'+this.y+'--'+this.color); returnthis.x+'--'+this.y+'--'+this.color; } } letcp=newColorPoint(25,8,'green'); cp.getData(); console.log(cpinstanceofColorPoint);//true console.log(cpinstanceofPoint);//true //instanceof运算符用来测试一个对象在其原型链中是否存在一个构造函数的prototype 属性。 |
注意:ColorPoint继承了父类Point,但是它的构造函数必须调用super方法。
Class的静态方法
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
classFoo{ staticclassMethod(){ return'hello'; } } Foo.classMethod()//'hello' varfoo=newFoo(); foo.classMethod() //TypeError:undefinedisnotafunction |
父类的静态方法,可以被子类继承。
classFoo{ staticclassMethod(){ return'hello'; } } classBarextendsFoo{ } Bar.classMethod();//'hello' |
静态方法也是可以从super对象上调用的。
classFoo{ staticclassMethod(){ return'hello'; } } classBarextendsFoo{ staticclassMethod(){ returnsuper.classMethod()+',too'; } } Bar.classMethod(); |
export命令
模块功能主要由两个命令构成:export和import。
export命令用于用户自定义模块,规定对外接口;
import命令用于输入其他模块提供的功能,同时创造命名空间(namespace),防止函数名冲突。
ES6允许将独立的JS文件作为模块,允许一个JavaScript脚本文件调用另一个脚本文件。
现有profile.js文件,保存了用户信息。ES6将其视为一个模块,里面用export命令对外部输出了三个变量。
//profile.js varfirstName='Michael'; varlastName='Jackson'; varyear=1958; export{firstName,lastName,year}; |
如果想为输入的变量重新取一个名字,import语句中要使用as关键字,将输入的变量重命名。
import{lastNameassurname}from'./profile'; 注意:浏览器测试为: import{firstName,lastName,year}from'./module/profile.js'; console.log(firstName); |
为加载模块指定默认输出,使用exportdefault命令。
//export-default.js exportdefaultfunction(){ document.write('foo'); } |
其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。
//import-default.js importcustomNamefrom'./export-default'; customName();//'foo' |
相关文章推荐
- Velocity快速入门教程-脚本语法详解
- HyperV视频教程 Hyper-V 3.0基础快速入门学习+HyperV集群部署与创建
- Spring boot学习教程之快速入门篇
- Java基础学习总结(25)——Log4j快速入门教程
- MyBatis入门学习教程(一)-MyBatis快速入门
- 快速学习MySQL索引的入门超级教程
- [新手入门]快速学习 ADO.NET Entity Framework系列文章 #3 -- LINQ-to-SQL、EntitySQL、查询产生器方法(Query builder)三种语法
- MyBatis入门学习教程 MyBatis快速入门
- ASP.NET MVC 5 学习教程:快速入门
- 屌丝逆袭--Asp.net快速入门学习教程 第1晚
- Lua脚本语言基本语法快速入门教程
- JavaScript的React框架中的JSX语法学习入门教程
- MyBatis入门学习教程 MyBatis快速入门
- 15个快速学习苹果Swift编程语言的入门教程
- GItHub----Makedown语法学习(快速入门)
- [转]ASP.NET MVC 5 学习教程:快速入门
- 15个快速学习苹果Swift编程语言的入门教程
- 快速学习MySQL索引的入门超级教程
- NetBeans工具学习之道:NetBeans IDE Java 快速入门教程
- Velocity快速入门教程-脚本语法详解(转)