关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » UI前端 »ES6箭头函数和它的作用域

    ES6箭头函数和它的作用域

    2015-03-12 00:00:00 出处:投稿
    分享

    在ES6很多很棒的新特性中, 箭头函数 (或者大箭头函数)就是其中值得关注的一个! 它不仅仅是很棒很酷, 它很好的利用了作用域, 快捷方便的在现在使用以前我们用的技术, 减少了很多代码……但是假如你不了解箭头函数原理的话可能就有点难以理解. 所以,让我们来看下箭头函数, 就是现在!

    执行环境

    你可以自己去学习和尝试下, 你可以简单的把示例程序代码复制到你的浏览器控制台下. 现在, 推荐使用Firefox(22+)开发者工具, Firefox(22+)开发者工具现在支持箭头函数,你也可以使用谷歌浏览器. 假如你使用谷歌浏览器, 你必须要做下列两件事: – - 在谷歌浏览器中地址栏中输入:”about:flags”, 找到 “使用体验性Javascript”选项,开启使用。 – - 在函数的开头加上”use strict”,然后再在你的谷歌浏览中测试箭头函数吧(提示:请用谷歌浏览器v38,我当时就是被浏览器版本坑了):

    (function(){
        "use strict";
        // use arrow functions here
    }());

    幸运的是后面会有越来越多的浏览器支持ES6特性. 现在你完成了所有准备工作, 让我们继续深入它吧!

    一个新话题

    最近大家在讨论关于ES6的一个话题:关于箭头函数, 像这样:

    =>

    新的语法

    随着讨论产生了一个新的语法:

    param => expression

    新增的语法是作用在变量上, 可以在表达式中申明多个变量, 下面是箭头函数的使用模式:

    //  一个参数对应一个表达式
    param => expression;// 例如 x => x+2;
    
    // 多个参数对应一个表达式
    (param [, param]) => expression; //例如 (x,y) => (x + y);
    
    // 一个参数对应多个表示式
    param => {statements;} //例如 x = > { x++; return x;};
    
    //  多个参数对应多个表达式
    ([param] [, param]) => {statements} // 例如 (x,y) => { x++;y++;return x*y;};
    
    //表达式里没有参数
    () => expression; //例如var flag = (() => 2)(); flag等于2
    
    () => {statements;} //例如 var flag = (() => {return 1;})(); flag就等于1
    
     //传入一个表达式,返回一个对象
    ([param]) => ({ key: value });
    //例如  var fuc = (x) => ({key:x})
            var object = fuc(1);
            alert(object);//{key:1}

    箭头函数是怎么实现的

    我们可以把一个普通函数转换成用箭头函数来实现:

    // 当前函数
    var func = function (param) {    
        return param.split(" ");
    }
    // 利用箭头函数实现
    var func = param => param.split(" ");

    从上面的例子中我们可以看出箭头函数的语法实际上是返回了一个新的函数, 这个函数有函数体和参数

    因此, 我们可以这样调用刚才我们创建的函数:

    func("Felipe Moura"); // returns ["Felipe", "Moura"]

    立即执行函数(IIFE)

    你能在立即执行函数里使用箭头函数,例如:

    ( x => x * 2 )( 3 ); // 6

    这行代码产生了一个临时函数,这个函数有一个形参x,函数的返回值为x*2,之后系统会马上执行这个临时函数, 将3赋值给形参x.

    下面的例子描述了临时函数体里有多行代码的情况:

    ( (x, y) => {
        x = x * 2;
        return x + y;
    })( 3, "A" ); // "6A"

    相关思考

    思考下面的函数:

    var func = x => {
        return x++;
    };

    我们列出了一些常见的问题:

    - 箭头函数创建的临时函数的arguments是我们预料的那样工作

    console.log(arguments);

    - typeof和instanceof函数也能正常检查临时函数

    func instanceof Function; // true
    typeof func; // function
    func.constructor == Function; // true

    - 把箭头函数放在括号内是无效的

    //  有效的常规语法
    (function (x, y){
        x= x * 2;
        return x + y;
    } (3, "B") );
    
    // 无效的箭头函数语法
    ( (x, y) => {
        x= x * 2;
        return x + y;
    } ( 3, "A" ) );
    
    // 但是可以这样写就是有效的了:
    ( (x,y) => {
        x= x * 2;return x + y;
    } )( 3,"A" );//立即执行函数

    - 尽管箭头函数会产生一个临时函数,但是这个临时函数不是一个构造函数

    var instance= new func(); // TypeError: func is not a constructor

    - 同样也没有原型对象

    func.prototype; // undefined

    作用域

    这个箭头函数的作用域和其他函数有一些不同,假如不是严格模式,this关键字就是指向window,严格模式就是undefined,在构造函数里的this指向的是当前对象实例,假如this在一个对象的函数内则this指向的是这个对象,this有可能指向的是一个dom元素,例如当我们添加事件监听函数时,可能这个this的指向不是很直接,其实this(不止是this变量)变量的指向是根据一个规则来判断的:作用域流。下面我将演示this在事件监听函数和在对象函数内出现的情况:

    在事件监听函数中:

    document.body.addEventListener('click', function(evt){
        console.log(this); // the HTMLBodyElement itself
    });

    在构造函数里:

    function Person () {
    
        let fullName = null;
    
        this.getName = function () {
            return fullName;
        };
    
        this.setName = function (name) {
            fullName = name;
            return this;
        };
    }
    
    let jon = new Person();
    jon.setName("Jon Doe");
    console.log(jon.getName()); // "Jon Doe"
    //注:this关键字这里就不解释了,大家自己google,badu吧。

    在这个例子中,假如我们让Person.setName函数返回Person对象本身,我们就可以这样用:

    jon.setName("Jon Doe")
       .getName(); // "Jon Doe"

    在一个对象里:

    let obj = {
        foo: "bar",
        getIt: function () {
            return this.foo;
        }
    };
    
    console.log( obj.getIt() ); // "bar"

    但是当执行流(比如使用了setTimeout)和作用域变了的时候,this也会变。

    function Student(data){
    
        this.name = data.name || "Jon Doe";
        this.age = data.age>=0   data.age : -1;
    
        this.getInfo = function () {
            return this.name + ", " + this.age;
        };
    
        this.sayHi = function () {
            window.setTimeout( function () {
                console.log( this );
            }, 100 );
        }
    
    }
    
    let mary = new Student({
        name: "Mary Lou",
        age: 13
    });
    
    console.log( mary.getInfo() ); // "Mary Lou, 13"
    mary.sayHi();
    // window

    当setTimeout函数改变了执行流的情况时,this的指向会变成全局对象,或者是在严格模式下就是undefine,这样在setTimeout函数里面我们使用其他的变量去指向this对象,比如self,that,当然不管你用什么变量,你首先应该在setTimeout访问之前,给self,that赋值,或者使用bind方法不然这些变量就是undefined。

    这是后就是箭头函数登场的时候了,它可以保持作用域,this的指向就不会变了。

    让我们看下上文起先的例子,在这里我们使用箭头函数:

    function Student(data){
    
        this.name = data.name || "Jon Doe";
        this.age = data.age>=0   data.age : -1;
    
        this.getInfo = function () {
            return this.name + ", " + this.age;
        };
    
        this.sayHi = function () {
            window.setTimeout( ()=>{ 
                // the only difference is here
                console.log( this );
            }, 100 );
        }
    
    }
    
    let mary = new Student({
        name: "Mary Lou",
        age: 13
    });
    
    console.log( mary.getInfo() ); // "Mary Lou, 13"
    mary.sayHi();
    // Object { name: "Mary Lou", age: 13, ... }

    分析:在sayHi函数中,我们使用了箭头函数,当前作用域是在student对象的一个方法中,箭头函数生成的临时函数的作用域也就是student对象的sayHi函数的作用域。所以即使我们在setTimeout调用了箭头函数生成的临时函数,这个临时函数中的this也是正确的指向。

    有趣和有用的使用

    创建一个函数很容易,我们可以利用它可以保持作用域的特征:

    例如我们可以这么使用:Array.forEach()

    var arr = ['a', 'e', 'i', 'o', 'u'];
    arr.forEach(vowel => {
        console.log(vowel);
    });

    分析:在forEach里箭头函数会创建并返回一个临时函数 tempFun,这个tempFun你可以想象成这样的:function(vowel){ console.log(vowel);}但是Array.forEach函数会怎么去处理传入的tempFunc呢?在forEach函数里会这样调用它:tempFunc.call(this,value);所有我们看到函数的正确执行效果。

    map里使用箭头函数,这里我就不分析函数执行过程了。。。。

    var arr = ['a', 'e', 'i', 'o', 'u'];
    arr.map(vowel => {
        return vowel.toUpperCase();
    });
    // [ "A", "E", "I", "O", "U" ]

    费布拉奇数列

    var factorial = (n) => {
        if(n==0) {
            return 1;
        }
        return (n * factorial (n-1) );
    }
    
    factorial(6); // 720

    我们也可以用在Array.sort方法里:

    let arr = ['a', 'e', 'i', 'o', 'u'];
    arr.sort( (a, b)=> a < b  1: -1 );

    也可以在事件监听函数里使用:

    document.body.addEventListener('click', event=>console.log(event, this)); // EventObject, BodyElement
    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    正版 Windows 11产品密钥怎么查找/查看?

    还有3个月,微软将停止 Windows 10 的更新

    Windows 10 终止支持后,企业为何要立即升级?

    Windows 10 将于 2025年10 月终止技术支持,建议迁移到 Windows 11

    Windows 12 发布推迟,微软正全力筹备Windows 11 25H2更新

    Linux 退出 mail的命令是什么

    Linux 提醒 No space left on device,但我的空间看起来还有不少空余呢

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    IT头条

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    液冷服务器概念股走强,博汇、润泽等液冷概念股票大涨

    01:17

    亚太地区的 AI 驱动型医疗保健:2025 年及以后的下一步是什么?

    16:30

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    技术热点

    商业智能成CIO优先关注点 技术落地方显成效(1)

    用linux安装MySQL时产生问题破解

    JAVA中关于Map的九大问题

    windows 7旗舰版无法使用远程登录如何开启telnet服务

    Android View 事件分发机制详解

    MySQL用户变量的用法

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。