zoukankan      html  css  js  c++  java
  • 箭头函数详解

    ES6标准新增了一种新的函数:Arrow Function(箭头函数)。

     

    1.基础语法

    通常函数的定义方法

    var fn1 = function(a, b) {

        return a + b

    }

     

    function fn2(a, b) {

        return a + b

    }

    使用ES6箭头函数语法定义函数,将原函数的“function”关键字和函数名都删掉,并使用“=>”连接参数列表和函数体。

    var fn1 = (a, b) => {

        return a + b

    }

     

    (a, b) => {

        return a + b

    }

    当函数参数只有一个,括号可以省略;但是没有参数时,括号不可以省略。

     

    // 无参

    var fn1 = function() {}

    var fn1 = () => {}

     

    // 单个参数

    var fn2 = function(a) {}

    var fn2 = a => {}

     

    // 多个参数

    var fn3 = function(a, b) {}

    var fn3 = (a, b) => {}

     

    // 可变参数

    var fn4 = function(a, b, ...args) {}

    var fn4 = (a, b, ...args) => {}

     

    箭头函数相当于匿名函数,并且简化了函数定义。箭头函数有两种格式,一种只包含一个表达式,省略掉了{ ... }和return。还有一种可以包含多条语句,这时候就不能省略{ ... }和return

    () => return 'hello'

    (a, b) => a + b

    (a) => {

      a = a + 1

      return a

    }

    如果返回一个对象,需要特别注意,如果是单表达式要返回自定义对象,不写括号会报错,因为和函数体的{ ... }有语法冲突。

     

    注意,用小括号包含大括号则是对象的定义,而非函数主体

    x => {key: x} // 报错

    x => ({key: x}) // 正确

    箭头函数看上去是匿名函数的一种简写,但实际上,箭头函数和匿名函数有个明显的区别:箭头函数内部的this是词法作用域,由上下文确定。(词法作用域就是定义在词法阶段的作用域。换句话说,词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的,因此当词法分析器处理代码时会保持作用域不变 。

     

    2. 箭头函数基本特点

    (1). 箭头函数this为父作用域的this,不是调用时的this

    箭头函数的this永远指向其父作用域,任何方法都改变不了,包括call,apply,bind。

    普通函数的this指向调用它的那个对象。

    let person = {

        name:'jike',

        init:function(){

            //为body添加一个点击事件,看看这个点击后的this属性有什么不同

            document.body.onclick = ()=>{

                alert(this.name);//?? this在浏览器默认是调用时的对象,可变的?                 

            }

        }

    }

    person.init();

     

    上例中,init是function,以person.init调用,其内部this就是person本身,而onclick回调是箭头函数,

    其内部的this,就是父作用域的this,就是person,能得到name。

    let person = {

        name:'jike',

        init:()=>{

            //为body添加一个点击事件,看看这个点击后的this属性有什么不同

            document.body.onclick = ()=>{

                alert(this.name);//?? this在浏览器默认是调用时的对象,可变的?                 

            }

        }

    }

    person.init();

    上例中,init为箭头函数,其内部的this为全局window,onclick的this也就是init函数的this,也是window,

    得到的this.name就为undefined。

     

    (2). 箭头函数不能作为构造函数,不能使用new

    //构造函数如下:

    function Person(p){

        this.name = p.name;

    }

    //如果用箭头函数作为构造函数,则如下

    var Person = (p) => {

        this.name = p.name;

    }

    由于this必须是对象实例,而箭头函数是没有实例的,此处的this指向别处,不能产生person实例,自相矛盾。

     

    (3). 箭头函数没有arguments,caller,callee

    箭头函数本身没有arguments,如果箭头函数在一个function内部,它会将外部函数的arguments拿过来使用。

    箭头函数中要想接收不定参数,应该使用rest参数...解决。

    let B = (b)=>{

      console.log(arguments);

    }

    B(2,92,32,32);   // Uncaught ReferenceError: arguments is not defined

     

    let C = (...c) => {

      console.log(c);

    }

    C(3,82,32,11323);  // [3, 82, 32, 11323]

     (4). 箭头函数通过call和apply调用,不会改变this指向,只会传入参数

    let obj2 = {

        a: 10,

        b: function(n) {

            let f = (n) => n + this.a;

            return f(n);

        },

        c: function(n) {

            let f = (n) => n + this.a;

            let m = {

                a: 20

            };

            return f.call(m,n);

        }

    };

    console.log(obj2.b(1));  // 11

    console.log(obj2.c(1)); // 11

     

    (5). 箭头函数没有原型属性

    var a = ()=>{

      return 1;

    }

    function b(){

      return 2;

    }

    console.log(a.prototype);  // undefined

    console.log(b.prototype);   // {constructor: ƒ}

     

    (6). 箭头函数不能作为Generator函数,不能使用yield关键字

     

    (7). 箭头函数返回对象时,要加一个小括号

    var func = () => ({ foo: 1 }); //正确

    var func = () => { foo: 1 };   //错误

     

    (8). 箭头函数在ES6 class中声明的方法为实例方法,不是原型方法

    //deom1

    class Super{

        sayName(){

            //do some thing here

        }

    }

    //通过Super.prototype可以访问到sayName方法,这种形式定义的方法,都是定义在prototype上

    var a = new Super()

    var b = new Super()

    a.sayName === b.sayName //true

    //所有实例化之后的对象共享prototypy上的sayName方法

     

    //demo2

    class Super{

        sayName =()=>{

            //do some thing here

        }

    }

    //通过Super.prototype访问不到sayName方法,该方法没有定义在prototype上

    var a = new Super()

    var b = new Super()

    a.sayName === b.sayName //false

    //实例化之后的对象各自拥有自己的sayName方法,比demo1需要更多的内存空间

    因此,在class中尽量少用箭头函数声明方法。

     

    (9). 多重箭头函数就是一个高阶函数,相当于内嵌函数

    const add = x => y => y + x;

    //相当于

    function add(x){

      return function(y){

        return y + x;

      };

    }

     (10). 箭头函数常见错误

    let a = {

      foo: 1,

      bar: () => console.log(this.foo)

    }

     

    a.bar()  //undefined

    bar函数中的this指向父作用域,而a对象没有作用域,因此this不是a,打印结果为undefined

     

    function A() {

      this.foo = 1

    }

     

    A.prototype.bar = () => console.log(this.foo)

    let a = new A()

    a.bar()  //undefined

    原型上使用箭头函数,this指向是其父作用域,并不是对象a,因此得不到预期结果

     

    3.一些this的指向实例

    var obj = {

      birth: 1990,

      getAge: function(){

        console.log(new Date().getFullYear() - this.birth); //this指向obj对象

     

      },

    }

    obj.getAge(); // 29

     

    var obj = {

        birth: 1990,

        getAge: function () {

            var b = this.birth; // 1990

            var fn = function () {

                return new Date().getFullYear() - this.birth; // this指向window或undefined

            };

            return fn();

        }

    };

    obj.getAge();// NaN

    var obj = {

        birth: 1990,

        getAge: function () {

            var b = this.birth; // 1990

            var fn = () => new Date().getFullYear() - this.birth; // this指向obj对象

            return fn();

        }

    };

    obj.getAge(); // 29

     

     

    var obj = {

           getAge: () => {

                console.log(this); // window

            }

        };

    obj.getAge(); //window

    作为对象的属性时,this的指向则不再是对象本身了,箭头函数捕获的是obj{}这个对象的环境,然后这个环境的this指向的是window

  • 相关阅读:
    创建Variant数组
    ASP与存储过程(Stored Procedures)
    FileSystemObject对象成员概要
    Kotlin 朱涛9 委托 代理 懒加载 Delegate
    Kotlin 朱涛 思维4 空安全思维 平台类型 非空断言
    Kotlin 朱涛7 高阶函数 函数类型 Lambda SAM
    Kotlin 朱涛16 协程 生命周期 Job 结构化并发
    Proxy 代理模式 动态代理 cglib MD
    RxJava 设计理念 观察者模式 Observable lambdas MD
    动态图片 Movie androidgifdrawable GifView
  • 原文地址:https://www.cnblogs.com/ranyonsue/p/11989281.html
Copyright © 2011-2022 走看看