实例
find()findlndex()
数组实例的find()用于找出第一个符合条件的数组元素。它的参数是一个回调函数,所右数组元素依次遍历该回调函数,直到找出第一个返回值为true的元素,然后返回该元素,否则返回undefined。
使用find()方法
[1,5,10,15].find(function(value,index,arr) { return value > 9 }) //10
从上面代码可以看到,回调函数接收3个参数,依次为当前的值、当前的位置和原数组。
数组实例的findindex()的用法与find()非常类似,返回第一个符合条件的数组元素的位置,如果所有元素都不符合条件,则返回-1.
[1,5,10,15].findIndex(function(value,index,arr) { return value > 9; }) // 2
这两个方法都可以接收第二个参数,用来绑定回调函数的this对象。另外,这两人方法都可以发现NaN,弥补了IndexOf的不足。
[NaN].indexOf(NaN) //-1 [NaN].findIndex(y => Object.is(NaN,y)) // 0
fill()
fill()使用给定值,填充一个数组。
使用fill()方法
['a','b','c'].fill(7) //(7,7,7] new Array(3).fill(7) //(7,7,7]
上面代码表明,fill()方法用于空数组的初始化非常方便。数组中已有的元素,会被全部抹去。fill()还可以接收第二个和第三个参数,用于指定填充的起始位置和结束位置
['a','b','c'].fill(7,1,2) //['a',7,'c']
entries()、keys()和values()
ECMAScript 6提供3个新的方法: entries()、keys()和values(),用于遍历数组。它们都返回一个遍历器,可以用for of循环进行遍历,唯一的区别是keys()是对键名的遍历values()是对键值的遍历,entries()是对键值对的遍历。例如:
for(let index of['a','b'].keys()) { console.log(index); } //0 //1
推导
ECMAScript 6提供简洁写法,允许直接通过现有数组生成新数组,这被称为数组推导。
下面代码通过for of结构,数组a2直接在a1的基础上生成。
var a1 = [1,2,3,4]; var a2 = [for (i of al) i * 2]; a2 // [2,4,6,8]
在数组推导中,for of结构总是写在最前面,返回的表达式写在最后面。
监听
Array.observe()和Array.unobserve()方法用于监听或取消监听数组的变化,指定回调函数。它们的用法与Object.observe和Object.unobserve()方法完全一致。唯一的区别是,对象可监听的变化一共有6种,而数组只有4种: add、update、delete、splice(数组的length属性发生变化)
对象
es6在es5基础上继续完善JavaScript对象系统,新增了多人静态方法和原型方法,完善了对象直接量的语法格式和用法灵活性,增强对象代理保护和监听控制。
新增方法
Object.is()
Object.is()用来比较两个值是否严格相等。它与严格比较运算符 (===)的行为基本-致,不同之处: +0不等于-0,NaN等于自身。
使用Object.is()工具函数比较两个值。
+0===-0 //true NaN-==NaN //false Object.is(+0,-0) //false Object.is (NaN,NaN) //true
Object.assign()
Object.assign()方法用来将源对象 (source) 的所有可枚举属性,复制到目标对象(target)。它至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象。只要有一个参数不是对象,就会抛出TypeError错误。
使用Object.assign()方法复制属性
var target = {a:1}; var sourcel = {b:2}; var source2 = {b:3} Object.assign(target, source1, source2) target // {a:1, b:2, c:3}
tips: 如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性
var target={ a: 1, b: 1 ); var sourcel={ b: 2,c: 2 ); var source2={b:3}: Object.assign(target, sourcel, source2) ; target //a:1, b:2, c:3)
原型方法
proto属性
proto属性用来读取或设置当前对象的prototype对象。该属性一度被正式写入ECMAScript 6草案,但后来又被移除。目前,所有浏览器 (包括IE 11)都部署了这个属性。
//es6的写法 var obj = { _proto_:someOtherObj, method:function() {...} } //es5的写法 var obj = Object.create(someOtherObj); obj.method=funtion() {...}
有了这个属性,实际上已经不需要通过Object.create()来生成新对象了
Obiect.setPrototypeOf()
Object.setPrototypeOf()方法的作用与proto相同,用来设置一个对象的prototype对象。基本用法如下:
function(obj,proto) { obj._proto_=proto; return obj; }
Object.getPrototypeOf()
该方法与setPrototypeOf()方法配套,用于读取一个对象的prototype对象。用法如下
Object.getPrototype0f(obj)
增强语法
es6允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
快速定义函数。
var Person = { name:'张三', //等同于 birth:birth birth, // 等同于 hello:funtion()... hello() {console.log('我的名字是',this.name)} }
这种写法用于函数的返回值,将会非常方便
function getPoint() { var x = 1; var y = 10; return {x,y}; } getPoint() //{x:1,y:10}
届性名表达式
es6允许定义对象时,用表达式作为对象的属性名。在写法上,要把表达式放在方括号内。
下面代码中,对象a的属性名lastWord是一人变量
var lastWord = "last word". var a = { "first word":"hello", [lastWord]:"world" } a["first word"] //"hello" a[lastWord] //"world" a["last word"] //"world"
符号数据
es6引入了一种新的原始数据类型Symbol。它通过Symbol()函数生成
下面代码中,Symbol()函数接收一个字符串作为参数,用来指定生成的Symbol的名称,可以通过name属性读取。typeof运算符的结果,表明Symbol是一种单独的数据类型
var mySymbol = Symbol("Test"); mySymbol.name // Test typeof mySymbol // "symbol"
注意: Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一人原始类型的值,不是对象。
代理防护层
引入对象代理层Proxy,Proxy可以理解成在目标对象之前,架设一层“拦载”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
es6原生提供Proxy构造函数,用来生成proxy实例对象。
var proxy = new Proxy({}, { get:function(target,property) { return 35; } }) proxy.time //35 proxy.name //35 proxy.title //35
上面代码就是Proxy构造函数使用实例,它接收两个参数,第一个是所要代理的目标对象 (上例是一个空对象),第二个是拦截函数,它有一个get方法,用来拦截对目标对象的访问请求。get方法的两个参数分别是目标对象和所要访问的属性。可以看到,由于栏截函数总是返回35,所以访问任何属性都得到35。
监听
Obiect.observe()方法用来监听对象 (以及数组)的变化。一旦监听对象发生变化,就会触发回调函数。
在下面代码中,Object.observe()方法监听一个空对象o,一旦o发生变化 (如新增或删除一个属性),就会触发回调函数
var o = {}; function observer(changes) { changes.forEach(funtion(change) { console.log("发生变动的属性:"+change.name); console.log("变动前的值:"+change.oldValue); console.log("变动后的值:"+change.object[change.name]); console.log("变动类型:"+change.type); }) } Object.observe(o,observer);
Object.observe()方法指定的回调函数,接收一个数组 (changes) 作为参数。该数组的成员与对象的变化一一对应,也就是说,对象发生多少个变化,该数组就有多少个成员。每个成员是一个对象 (change) ,它的name属性表示发生变化源对象的属性名oldValue属性表示发生变化前的值,object属性指向变动后的源对象,type属性表示变化的种类。基本上,change对象是下面的样子。
var change = { object:{...}, type:'update', name:'p2', oldValue:'property 2' }
Object.observe()方法目前共支持监听6种变化。
add: 添加属性.
update: 属性值的变化
delete: 删除属性,S
setPrototype: 设置原型<
reconfigure: 属性的attributes对象发生变化
preventExtensions: 对象被禁止扩展
Object.observe()方法还可以接收第三个参数,用来指定监听的事件种类。用法如下
Object.observe(o, observer, ['delete']) .
上面代码表示,只在发生delete事件时,才会调用回调函数
Obiect.unobserve()方法用来取消监听
Object.unobserve(o, observer)
提示: Object.observe()和Object.unobserve()这两个方法不属于ECMAScript 6,而是属于ES7的一部分,Chrome 36已经开始支持了。
函数
es6增强了JavaScript函数功能,改进了很多函数定义的方式,使函数使用更方便、更高效
默认值
在es6之前,不能直接为函数的参数指定默认值,只能采用变通的方法。例如:
function log(x, y) { y = y || 'World' console.log(x,y); } log('Hello')//输出: Hello World log('Hello','China') //输出: Hello China log('Hello','') //输出: Hello World
上面代码检查函数log的参数有没有赋值,如果没有,则指定默认值为World。这种写法的缺点在于,如果参数y赋值了,但是对应的布尔值为false,则该赋值不起作用。就像上面代码的最后一行,参数v等于空字符,结果被改为默认值。
为了避免这个问题,通常需要先判断一下参数y是否被赋值,如果没有,再等于默认值
例如:
// 写法一 if(typeof y === 'undefined') { y = 'World'; } // 写法二 if(arguments.length === 1) { y = 'World'; }
es6允许为函数的参数设置默认值,即直接写在参数定义的后面。
function log(x,y='World') { console.log(x,y); } log('Hello') //输出:Hello World log("Hello",'China') //输出:Hello China log("Hello",'') //输出:Hello
可以看到,ECMAScript 6的写法比ECMAScript 5简洁许多,而且非常自然
下面代码为函数的参数设置默认值。
function Point(x=0,y=0) { this.x = x; this.y = y; } var p = new Point(); //结果:p = {x:0,y:0}
rest函数
es6引入rest参数 (…变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
下面代码中的add()函数是一个求和函数,利用rest参数,可以向该函数传入任意数目的参数。
function add(...values) { let sum = 0; for(var val of values) { sum+=val; } return sum; } add(2,5,3) //10
rest参数中的变量代表一个数组,所以数组特有的方法都可以用于这个变量.