ECMAScript6简介和学习笔记(二)数组 函数 对象

    这次我们来谈谈数组、函数、对象,这三个家伙出现的频率太高了。在整个js的体系中占据着非常重要的位置。es6对其的优化扩展也是整个es6比较重要的部分。

数组

    首先来谈谈数组,划重点开始喽,个人觉得可能简洁写法、解构赋值、扩展运算符,可能出现的频率比较高一点。
    先介绍几个很有用的方法:

Array.from() 转换为数组

    将类似数组的对象和可遍历的即有iterator接口的对象转化为真正的数组,在实际应用中dom的nodelist对象和函数中arguments对象是常用的对象。
    另外稍微提及一下,扩展运算符(...)同样可以将某些数据结构转化为数组,但相比Array.from,它只能转换含有iterator接口的结构,而Array.from可以转换所有带有length属性的对象,包括字符串(可以正确处理大于\uFFFF的Unicode字符)。
Array.from({length:3});
//[ undefined, undefined, undefined]
    同时,Array.from可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理并将处理后的值放入数组,如果在第二个值中用到了this,还可以接受第三个参数用来绑定this的指向。
    配合三个参数,Array.from实际上实现了把一个原始的数据结构通过一系列函数处理变为数组,进而可以用强大的数组方法来进行数据的处理。

Array.of() 数值转化为数组

    Array.of与Array.from有异曲同工之妙,用于将一组值转换为数组,而它又与Array()、New Array()有什么区别呢?
    其实Array.of基本可以替代Array()、New Array(),并且不存在采纳数不同而导致的重载,他的行为是统一的,只会把传入的参数认为是数组成员而不是数组长度。
Array.of(3);//[3]
Array(3);//[,,,]

copyWithin() 数组元素复制

    在当前数组内将指定位置的成员复制到其他位置(会覆盖原有成员),返回值是当前数组(修改后的数组),使用这个函数会修改当前数组。

find() findIndex() 寻找数组内元素

    find方法用于找出第一个符合条件的数组成员,参数为回调参数,对所有数组成员执行回调函数,直到出现第一个返回值为true的成员,然后返回该成员,如果没有符合条件的成员,就返回undefined。
    findIndex与find十分类似,只是返回值是数组成员位置,如果么有符合成员则返回-1.
    另外两个函数都可以接受第二个参数,用来绑定回调函数的this,而且两个方法都可以用于发现NaN,弥补了indexOf的不足。

fill() 填充数组元素

    fiil用于使用给定值填充数组,第一个参数为填充的给定值,第二个第三个参数指定填充的起始位置和结束位置。

entries() keys() values() 遍历数组的三种方法

    分别是对键值对、键名、键值的遍历,可用for...of循环。

includes() 数组是否包含给定值

    该方法属于es7,第二个参数表示搜索的起始位置

数组空位让数组从此undefined

    数组的空位指数组的某一个位置没有任何值,没有任何值不代表是undefined,undefined是有值的。es5中空位并不明确,但es6中明确规定空位转为undefined。但是es5中的各种方法还是会对空位处理不统一,所以建议避免空位。

数组推导强大的简洁写法

    es6里在[]里就可以随意写入变量作为成员,es7里数组推导更提供了简洁写法,允许直接通过现有数组等有iterator接口的数据结构生成新数组。
var a1=[1,2,3,4];
var a2=[for(i of a1) i*2];
    注意数组推导中,for...of结构总是写在最前面,返回的表达式写在最后面。
    表达式部分比较灵活,可以连用多个if语句筛选,它实际上就可以替代了之前使用的map和filter方法。
    另外需要注意的是,方括号里在数组推导过程中实际上是进行了一个类似函数的行为,所以方括号内是一个单独的作用域;数组推导中,新数组是立即在内存生成,如果原数组过大,将非常消耗内存;字符串可以进行for...of循环,所以和Array.from一样字符串也可以用于数组推导。

函数

    es6为函数增加了许多便利的属性和使用的福利,减少了一些不必要的麻烦,也加了许多提升性能的红利。
    下面开始划重点:

函数参数默认值

    这方面在本系列博客的前一篇中也有所提及,所以本篇只是粗略讲讲。
    在函数机制里,参数是默认声明的,即可以认为是在函数内部首行隐藏了一条参数定义语句,只是默认值是在函数执行时才会运行,如果给予了正确的参数值,也就是默认值未生效的话,默认值是不会执行的。函数参数默认值可以直接在函数定义时加到参数声明括号里,形如
function(a,b=0){}

function a(a=0,b){}
a(,1)//报错
a(undefined,1) // [1,1]
    另外还需要注意几点:
    1.如果在非尾部函数参数定义了默认值,其实是不可以省略的,除非显式的输入undefined,见上面代码。

    2.理论上来说函数的length属性指函数的形参个数,但不严格的说,在设置默认参数后则返回没有指定默认值的形参个数,总体来说,应用函数默认值后,length可能会和我们预期值不相同,length可以理解为期望传入的参数个数,设置了默认值自然就不是被期望的了,但是在chorme的56版测试的length结果是:
    第一个设置默认参数的形参前的形参个数
(function a(a=1,b){}).length    //0
(function a(a,b=1){}).length    //1
(function a(a,c,b=1){}).length  //2
(function a(a,c,d,b=1){}).length    //3
(function a(a,c=2,d,b=1){}).length  //1
    3.如果参数默认值是一个变量,那么该变量所处的作用域就是本函数的作用域。

    4.此外默认参数的应用是非常灵活的,比如将默认参数设置为一个执行的函数,如mustBeProvided = throwError(),若不提供则执行函数并返回结果,实际上定义了一个必须传入的参数,否则则报错。

rest参数

    rest参数用于获取多余的参数,形如function(...value),实际上可以用value替代arguments,但要注意的是rest参数后不能有其他参数,否则会报错,另外rest参数无法反映到函数的length属性中。

扩展运算符

    扩展运算符是是三个点(...),类似于rest参数的逆运算,它是将数组解析成用逗号分隔的参数序列,同样在将扩展运算符运用到赋值中时,只能将其放在最后一位,否则会报错,扩展运算符的应用十分广泛,给参数赋值、数组合并、函数数组返回值、解析数组带来了极大的便利。
let values = [1,2,3,4]
[0,...values]  //[0,1,2,3,4]

箭头函数

    十分洋气炫酷的箭头函数(=>),x => x,一行简洁的代码就可以写出原来需要三行的函数functoin (x){return x},如果不需要参数或者多个参数,就用圆括号代表或包裹参数部分。
    另外还有几个注意点:
    1.如果箭头函数的代码块部分多于一条语句,就要使用大括号将其括起来,并使用return语句返回,但是当箭头函数直接返回一个对象时,就需要在对象{}外面加上()。
    2.this的指向。函数体内的this指向定义时所在的对象,而不是使用时所在的对象,其实箭头函数自身没有自己的this,所以内部的this就是外层作用域的this。
    3.不可以当作构造函数,不可以使用new命令
    4.不可以使用arguments对象
    5.不可以使用yield命令
    6.没有super、new.target变量

函数绑定

    es7的一个提案,绑定运算符是并排的双冒号(::),双冒号左边是对象,this将绑定在它身上,右边是要执行绑定的函数,返回的结果仍然是原函数,如果左边的对象为空,右边的是一个对象的方法,则this绑定在该对象上。

尾调用优化

    尾调用时函数式编程的一个重要概念,指某个函数的最后一步是调用另一个函数,最后一步必须只是单纯地调用函数,下面给出正确写法和一些错误写法
function f(x){
    return g(x);
}

//以上是正确的尾调用写法
//以下是错误的尾调用写法

function f(x){
    y=g(x);
    return y;
}

function f(x){
    g(x);
}

function f(x){
    return g(x)+1;
}
    尾调用在递归调用优化里面十分有用,如果在递归调用里面不采用尾调用,那么在每次递归时上一个函数并没有完全执行完毕,还保留着引用在调用栈里面,一旦递归次数过多,那么将会占用很大的内存,而尾递归优化后,每次递归时上一个函数调用下一个函数就是最后一个步骤了,本函数已经结束,所以直接在调用栈里用新函数覆盖旧函数的调用即可。

对象

属性简洁表示方法

    和数组一样,es6允许直接写入变量和函数作为对象的属性和方法,下面分别给出属性和方法简写的例子
var foo="bar";
var baz={foo};
baz//{foo:"bar"}

function f(){
    return {x,y};
}

var o={
    method(){//不用累赘的function
        return "hello";
    }
};
var t={o.method};

属性名表达式

    可以直接使用表达式标识作为属性名和方法名,表达式放在中括号里面
let a="foo";
let obj={
    [a]:true,
    ["a"+"b"]:false,
    ["h"+"i"](){
        return "hello";
    }
};
    但是千万要注意,属性名表达式和简洁表示方法不能同时使用,[]里面不能存放变量,否则会报错。另外如果觉得这样的对象还不够给力,可以看看我后面的博客里介绍的数据结构map,将键名极大扩展。

Object.is() Object.assign()

    object.of()用来比较两个值是否严格相等,它与严格比较运算符(===)行为基本一致,不同之处有两个+0和-0不相等,而且NaN与NaN相等。
    Object.assign()用来将源对象的所有可枚举的属性复制到目标对象中,第一个参数为目标对象,后面的都是参数也就是被复制对象。不可枚举的属性和继承的属性不会被复制,复制时后面的属性会覆盖前面的属性。

属性遍历

1.for in遍历,不过会遍历原型链上继承的其他方法,而且顺序可能会有一些问题
2.Object.keys(obj),会返回键名数组
3.Object.getOwnPropertyNames(obj),返回数组,包含自身所有属性,不包含symbol属性,但包含不可枚举属性
4.Object.getOwnPropertySymbols(obj),返回数组,包含对象自身所有symbol属性
5.Reflect.ownKeys(obj),返回一个数组,包含所有属性
6.Reflect.enumerate(obj),返回一个iterator对象,遍历对象自身的和继承的所有可枚举属性,不包含symbol属性,基本与for in类似

最后提一点,es7提案将rest参数和扩展运算符(…)引入对象。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值