ES6箭头函数(=>)和拓展运算符(...)

本篇文章为this整理的拓展,在JavaScript编写过程中,充分使用ES6的特性,可以有效减少this的错误引用

匿名函数与箭头函数:

匿名函数,又称lambda,通常在无需给函数命名的场景下使用,目前许多语言都支持lambda语法(C++11、JAVA8开始也支持lambda)。
  JavaScript中的匿名函数长这样↓:

//了事拂袖去,深藏功与名.
(function(){
  //do something
})()
//数组排序
var arr = ["11","8","33", "9", "7", "10", "12"];
var newArr = arr.sort(function(a,b){
  return Number(a) - Number(b)
})

JavaScript的箭头函数与匿名函数,在用法上大同小异↓:

a.箭头左边为参数,箭头右边跟返回值

(a,b,c)=>a*b*c

b.箭头右边跟代码块

(a,b)=>{
  var c = a*a + b*b
  return Math.sqrt(c); // 返回值可选,用法和普通函数一样
}

c.单一参数,括号可以省略(无参数必须要括号)

a=>a*2-1

用法:

//作为参数传入:
var timer = setTimeout(()=>{
  console.log('bang!')
},1000)
var array = [1,2,3,4,5]
var sum = array.reduce( (prev,next)=>prev+next )//15
//赋值:
var isLeapYear = (year)=>{
  if( year%4 === 0 && year % 100 !== 0 ){
    return true;
  } else {
    return false;
  }
}
isLeapYear(2018) // false

箭头函数看起来比function(){}简洁多了,然而箭头函数并不仅仅是因为为了简介才设计出来,尽管跟function(){}用法相同,使用的时候还是需要注意一些问题:

1.箭头函数不会再其作用域生成this
对照xiaoming作用域下的三个变量:

var xiaoming = {
    age:18,
    getAge:function(){
        var xiaomingsAge= this.age;//this是xiaoming
        var getAgeWithLambda = ()=>this.age;//this还是xiaoming
        var getAgeWithFunction = function(){
            return this.age;// this是window,
            //window下没有声明age变量,故为undefined
        }//对照
        console.log(xiaomingsAge)//18
        console.log(getAgeWithLambda())//18
        console.log(getAgeWithFunction())//undefined
    }
}

这意味着在箭头函数中引用的this跟当前作用域保持一致,ES6之前保存this,有人会这么做(把this存为一个变量)↓:

//做一个1秒后爆炸的定时炸弹!
//no more
var bomb = {
  sound:"boooooooom!!",
  detonate:function(){
      const that = this;
      setTimeout(function(){
         console.log(that.sound)
      },1000)
   }
}

或者这么做(调用bind(this))↓

//no more!!
var bomb = {
  sound:"boooooooom!!",
  detonate:function(){
      setTimeout(function(){
         console.log(this.sound)
      }.bind(this),1000)
   }
}

有了箭头函数以后↓

//you can do like this!
var bomb = {
  sound:"boooooooom!!",
  detonate:function(){
      setTimeout(()=>{
         console.log(this.sound)
      },1000)
   }
}

2.箭头函数不再有prototype

var lambda = ()=>0;
console.log(lambda.prototype) //undefined

3.箭头函数无法作为构造器(new构造)或生成器(但仍可以被async修饰)

var lambda = (a)=>{this.a = "aaa"}
new lambda(a) //TypeError: lambda is not a constructor
var gen = *(a)=>{
  yield a++
}//SyntaxError: Unexpected token *

4.箭头函数作用于内不会再生成arguments
原理同this

function showArgs(){
    console.log(arguments)
}
showArgs(1,2,3,4,5);// 打印arguments对象

var showLambdaArgs = ()=>{
    console.log(arguments);
}
showLambdaArgs(1,2,3,4,5);//arguments is not definded!

上级作用域的arguments,在箭头函数中不变:

    function plus (a,b){
        var a  = arguments
        console.log('plus:',arguments); // arguments[2,3]
        ((c,d)=>{
              console.log('lambda:', arguments);//arguments [2,3]
              console.log(a === arguments);//true
        })(4,5)
    }
    plus(2,3)

如果我一定要引用传入的参数怎么办?答↓:

拓展运算符(Spread syntax):

拓展运算符允许一个可迭代的对象(数组、类数组对象、字符串、ES6中的Set、Map等拥有默认迭代器Symbol(Symbol.iterator)属性,可以被for...of遍历的对象)去拓展函数调用的参数、数组的元素,同时也允许以Object键值对的形式去拓展另一个对象

概念看看就好,不理解就往下看
(1)长啥样?

...

(2)怎么用?
记下文加粗字体就行

a1.在上文中,如果想引用箭头函数的参数,就在参数声明里拓展,拓展出来的参数就是一个真正的数组(化参数为数组)

var showLambdaArgs = (...foo)=>{
  return foo
}
showLambdaArgs(1,2,3,4,5,6)//[1,2,3,4,5,6]

//在普通函数中也能使用,注意与arguments的区别
function showArgs(...foo){
    console.log(arguments instanceof Array)// false
    console.log(foo instanceof Array)// true;
}

a2.也可以先定义固定参数,再引用接受剩余的参数:
注意,剩余参数必须放到最后,此后不能再跟其他参数(仅限a1,a2其他用法无此限制)

function introduce(name,age,...args){
   console.log(name)
   console.log(age)
   console.log(args)//an array
}
introduce("xiaoming","male",192,1920000,19.2,true);
//xiaoming,male,[192,1920000,19.2,true]
function wrongUsage(a,b,...c,d){
}//SyntaxError

b.调用函数时,把一个可迭代对象拓展传入,这个对象里面的元素就会变成单独的参数(化数组为参数)

function introduce(){
   console.log(arguments)//对象
   console.log(arguments.length)//参数个数
}
introduce(1,2,3,...[8,9,0])// arguments对象 和 6
introduce(4,5,..."abcde")// arguments对象 和 7

前文中原本需要 Math.max.apply(null,[a,b,c])的调用,变得简简单单:

Math.max(...[11,2,5,99,1]) //99
Math.min(...[11,2,5,99,1]) //1

c.化可迭代对象为数组

//字符串转化为数组
[..."ABCDEFG"] //["A", "B", "C", "D", "E", "F", "G"]
//解构赋值也可以这么用
var [a,b,c] = [...'123']//a = 1;b = 2;c = 3
//拓展运算的对象不用非得放在最后:
["a",..."bcdefg","h","i"]//["a", "b", "c", "d", "e", "f", "g", "h", "i"]
//一行去重数组ver2:
[...new Set([1,1,2,3,3,4,4,4])] //1 , 2 , 3 ,4
//倒序参数
function reverseArgs(){
  return [...arguments].reverse()//现在可以调用数组方法了
}
reverseArgs(1,2,3,4,5)//[5, 4, 3, 2, 1]

d.拓展对象:
对象的拷贝方法五花八门,
有JSON.parse(JSON.stringify(obj))的
有for(var i in obj){}赋值的
使用ES6的Object.assign()可能是大多数使用ES6开发者的选择:

var o = {a:1,b:2}
var p = Object.assign({},o)
console.log(o === p) //false

也可以使用拓展运算:

var object = {a:1,b:2}
var prince = {...object } 
console.log( prince )// {a: 1, b: 2}
console.log(object  === prince ) // false

不仅如此,对象可以实现任意次数和位置的拓展:

//也可以任意拓展:
var object = {a:1,b:2}
var queen = {c:3,d:4}
var rose = {
  zero:0,
  ...object,
  ...queen,
  last:666
}
console.log( rose )//"{"zero":0,"a":1,"b":2,"c":3,"d":4,"last":666}"

结束语

虽说是前文的拓展,但是与this相关的讲解不算紧密相连,大概是es6有意地弱化了开发者对this和arguments依赖的结果吧。本来想一口气顺带连class也介绍的,但class的内容足够放到一篇新的文章去了(容我踩一脚刹车,有空再写:-)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343