• ES6入门五:箭头函数、函数与ES6新语法


    • 箭头函数的基本用法与特点
    • 函数与ES6新语法

     一、箭头函数的基本用法与特点

    • 声明箭头函数采用声明变量和常量的关键字:var、let、const
    • 箭头函数的参数:没有参数用"()"空括号表示、一个参数可以不写括号、多个参数用"(a,b,c)"括号包裹
    • 使用箭头“=>”连接参数与执行块"{}"。
    • 如果执行块内只有return语句,可以不写大括号“{}”和return关键字。
    1 //ES6箭头函数
    2 const foo = (x,y) => x + y;
    3 //ES5编译结果
    4 var foo = function foo(x, y) {
    5   return x + y;
    6 };

    箭头函数的特点

    • 不写function关键字
    • 只能作为函数使用,不能使用nwe构建对象,因为没有Function原型
    • 箭头函数的参数不能重复名
    • 内部arguments、this由定义时外围最近一层的非箭头函数的arguments和this决定值

    这里我暂时先不解析箭头函数的特点,而是要说明一点,虽然箭头函数语法被称赞简洁、清晰明了、可读性强,真的如此?先来看下面这个示例:

     1 //ES6的一个箭头函数示例
     2 var dollabillsyall = (strings, ...values) =>
     3     strings.reduce( (s, v, idx) => {
     4         if(idx > 0){
     5             if(idx > 0){
     6                 if(typeof values[idx - 1] == "number"){
     7                     s += `$${values[idx - 1].toFixed(2)}`;
     8                 }else{
     9                     s += values[idx - 1];
    10                 }
    11             }
    12             return s + v;
    13         }
    14     },"");
    15 //ES5的编译结果
    16 var dollabillsyall = function dollabillsyall(strings) {
    17   for (var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
    18     values[_key - 1] = arguments[_key];
    19   }
    20 
    21   return strings.reduce(function (s, v, idx) {
    22     if (idx > 0) {
    23       if (idx > 0) {
    24         if (typeof values[idx - 1] == "number") {
    25           s += "$".concat(values[idx - 1].toFixed(2));
    26         } else {
    27           s += values[idx - 1];
    28         }
    29       }
    30 
    31       return s + v;
    32     }
    33   }, "");
    34 };

    当你看到上面这个示例后你还会觉得箭头函数简洁、清晰明了吗?从代码解构上来说明显可以感觉到编译成ES5反而更清晰。所以箭头函数的简洁、清晰明了、可读性强是有前提的,就是函数比较简短的情况下才能体现出箭头函数的优势。千万不要一味的追求新语法而不作选择的修改代码的编写方式,这明显是不明智的行为。

    1.1箭头函数不能被当作构造函数来使用:

    1 let foo = () => {
    2     this.a = 10;
    3 }
    4 new foo();//foo is not a constructor :foo不是一个构造函数

    1.2全局作用域下的箭头函数没有arguments:

    1 let sum = () =>{
    2     console.log(arguments);
    3 }
    4 sum();//ReferenceError: arguments is not defined at sum :arguments没有定义

    1.3全局作用域下的箭头函数的this指向window(非严格模式下):

     1 //ES6全局作用域下的箭头函数this的指向
     2 var foo = () => {
     3     console.log(this);
     4 }
     5 foo(); //window --不使用babel编译的执行结果
     6 //ES5的编译的结果
     7 "use strict";
     8 var _this = void 0;
     9 var foo = function foo() {
    10   console.log(_this);
    11 };
    12 foo(); //undefined--这是因为严格模式下函数自执行this指向undefined

    1.4前面两个示例都印证了箭头函数的arguments、this在定义时由外围的最近一层非箭头函数的arguments和this决定,所以在全局上没有arguments和全局函数的this指向window。按照这个说法,如果声明一个对象,然后对象的属性引用了全局定义的函数,采用对象引用执行其this也是指向window。这个毫无疑问,的确时这样,请看示例:

    1 var a = 'outerObj';
    2 var foo = () => {
    3     console.log(this.a);
    4 }
    5 let obj = {
    6     a: 'innerObj',
    7     fn:foo
    8 }
    9 obj.fn();//outerObj : obj.fn引用的时全局的foo箭头函数,其this是定义是就确定的

    1.5一定请注意前面的定义,箭头函数的this和arguments由定义时的最近的非箭头函数的arguments和this决定,所以即便在全局的对象上直接写到对象上的箭头函数,其this指向也是window。

    1 var a = 'outerObj';
    2 let obj = {
    3     a: 'innerObj',
    4     fn:()=>{
    5         console.log(this.a);
    6     }
    7 }
    8 obj.fn();//outerObj : obj是全局对象,obj.fn是箭头函数,所以其this指向了widnow

    1.6前面所证明的还是只箭头函数的外层没有函数的情况(全局箭头函数、引用执行全局箭头函数、全局对象上定义的箭头函数),其this指向都是window,接着来看这个示例,证明箭头函数的this指向外层最近的非箭头函数的this。

     1 var a = 'outerObj';
     2 var obj = {
     3     a:"innerObj",
     4     fn(){
     5         return () => {
     6             console.log(this.a);
     7         }
     8     }
     9 }
    10 var obj1 = {
    11     a:"strObj1"
    12 }
    13 var foo = obj.fn();
    14 obj1.foo = obj.fn();
    15 foo(); //innerObj
    16 obj1.foo(); //innerObj

    1.7使用箭头函数修正异步函数执行的this指向(以定时器为例):

     1 //使用箭头函数的this指向特性修正异步函数执行的this指向
     2 var obj = {
     3     a:"innerObj",
     4     fn(){
     5         setTimeout(() => {
     6             console.log(this.a);
     7         },1000);
     8     }
     9 }
    10 obj.fn(); //innerObj
    11 //ES5中的编译结果(也是我们之前解决异步函数执行this指向的常用方法)
    12 var obj = {
    13   a: "innerObj",
    14   fn: function fn() {
    15     var _this = this; //变量缓存this
    16 
    17     setTimeout(function () {
    18       console.log(_this.a); //通过函数的作用找到缓存this的变量
    19     }, 1000);
    20   }
    21 };
    22 obj.fn();

    关于箭头函数使用的小总结:

    • 函数中只有唯一语句return某个计算出的值,适应箭头函数;
    • 函数内部没有this引用,且没有自生引用(递归、事件绑定、解除绑定),适应箭头函数;(this引用可以用来特殊处理this指向,灵活应用)
    • 如果内层函数表达式依赖封装函数中某种像var args = Array.prototype.slice.call(arguments)来保证arguments的词法复制,那么这个内层函数应该可以安全地使用箭头函数。
    • 函数声明、较长的多语句函数表达式、需要词法名称标识(递归等)的函数,以及任何不符合以上几个特征的函数——尽量避免使用箭头函数

     二、函数与ES6新语法

     2.1箭头函数省略return关键字和{}不能适应返回一个对象字面量的值:

    1 //ES6箭头函数返回对象字面量值(错误代码)
    2 let sum = (a, b) => {a:a, b:b};
    3 //被识别成下面这段代码(错误代码)
    4 let sum = (a, b) => {
    5     a:a, b:b;
    6     return undefined;
    7 };
    8 //解决方法就是将返回的对象字面量变成一个表达式(正确代码)
    9 let sum = (a, b) => ({a:a, b:b});

    2.2使用箭头函数改善高级函数的结构:

     1 //ES5高级函数的场景示例
     2 function foo(x){
     3     return function(y){
     4         return function(z){
     5             return x + y + z;
     6         }
     7     }
     8 }
     9 console.log(foo(1)(2)(3));//6
    10 //ES6应用箭头函数简化高级函数结构
    11 let foo = x => y => x => x + y +z;
    12 console.log(foo(1)(2)(3));//6

     2.3默认参数的函数的参数长度--背后说明的默认参数的底层实际是在执行时向arguments上添加的数据:

    1 console.log((function (a){}).length);//1
    2 console.log((function (b=5){}).length);//0
    3 console.log((function (a,b,c=10){}).length);//2

     2.4匿名函数的名称在ES5与ES6中的差异,ES5的name属性不会返回匿名函数所属的变量名称(函数名),而在ES6中则是返回函数所属的变量名称(函数名)看下面的示例。对于具名函数无论被赋值于谁,在ES5和ES6中都是返回具名函数原始的函数声明名称。

    1 var f = function(){}
    2 //ES5
    3 f.name //"",空字符串
    4 //ES6
    5 f.name //"f",函数名
  • 相关阅读:
    android activity状态的保存
    java android 序列号serializable和parcelable
    java 中的 自定义viewUtils框架
    CSS隐藏元素的几种妙法
    WCF、WebAPI、WCFREST、WebService之间的区别
    前端大全
    最全前端资源汇集
    Unicode和汉字编码小知识
    关于写保护
    js实现密码加密
  • 原文地址:https://www.cnblogs.com/ZheOneAndOnly/p/11355437.html
Copyright © 2020-2023  润新知