资讯专栏INFORMATION COLUMN

关于ES6中箭头函数的this问题

LeviDing / 1329人阅读

摘要:对象的指向是可变的,但是在箭头函数中,它是固定的。同样的由于箭头函数没有自己的所以传统的显性绑定无效内部的指向外部在的学习中,的指向问题一直是个难点,特别是在对象方法中使用时,必须更加小心。由此箭头函数在很大程度上减少了我们的困扰。

什么是箭头函数 用法

ES6 允许使用“箭头”(=>)定义函数

  

测试

var p1 = document.getElementById("test1"); p1.addEventListener("click", () => { p1.style.color = "red"; }, false);

在es5中相当于

 var p1 = document.getElementById("test1");
   p1.addEventListener("click", function () {
             //直接通过dom的方法改变颜色
             this.style.color = "red"; 
      },false);

但是我们思考一个问题——当我们把第一段代码中的p1换成this时
this会指向哪里

p1.addEventListener("click", () => {
         
      this.style.color = "red";//   "color" is not undefined
     }, false);

这时我们就会想this为什么没有作用,而在es5中this是指向了p1

箭头函数有个使用注意点。

函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
this对象的指向是可变的,但是在箭头函数中,它是固定的。

function foo() {
  setTimeout(() => {
    console.log("id:", this.id);
  }, 100);
}

var id = 21;

foo.call({ id: 42 });
// id: 42

上面代码中,setTimeout的参数是一个箭头函数,这个箭头函数的定义生效是在foo函数生成时,而它的真正执行要等到100毫秒后。如果是普通函数,执行时this应该指向全局对象window,这时应该输出21。但是,箭头函数导致this总是指向函数定义生效时所在的对象(本例是{id: 42}),所以输出的是42

箭头函数的this

this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this,所以也就不能用作构造函数

// ES6
function foo() {
  setTimeout(() => {
    console.log("id:", this.id);
  }, 100);
}

// ES5
function foo() {
  var _this = this;

  setTimeout(function () {
    console.log("id:", _this.id);
  }, 100);
}

上面代码中,转换后的es5清楚地说明了,箭头函数里面根本没有自己的this,而是引用外层的this。

由于箭头函数没有自己的this,所以当然也就不能用call()、apply()、bind()这些方法去改变this的指向。

(function() {
  return [
    (() => this.x).bind({ x: "inner" })()
  ];
}).call({ x: "outer" });
// ["outer"]

同样的由于箭头函数没有自己的this 所以bind传统的显性绑定无效 内部的this指向外部this
在javascript的学习中, this的指向问题一直是个难点,特别是在对象方法中使用this时,必须更加小心。由此箭头函数在很大程度上减少了我们的困扰。

箭头函数this词法

话又说回来,当我们使用箭头函数时不使用常规的四种this绑定,又该怎么决定this的指向问题呢?
箭头函数是根据外层(函数或者全局)作用域来决定this

让我们看看箭头函数的此法作用域:

   function foo() {
            //返回箭头函数
            return(a) => {
                //this 继承自foo()
                console.log(this.a);
            };
        }
        var obj1 = {
            a:2
        };
        var obj2 ={
            a:3
        };
        var bar = foo.call(obj1);
        bar.call(obj2); //是2, 不是3!!!

foo()内部创建的箭头函数会捕获调用时foo()的this。由于foo()的this绑定到了obj1,所以bar(引用箭头函数)的this也会绑定到obj1,上文说过箭头函数this对象的指向是固定的所以后面的call修改不了绑定,即使是new也不行。

箭头函数可以像bind()一样确保函数的this被绑定到指定对象上,此外, 其重要性还体现在它更常见的词法作用域取代了传统的this的机制。实际上, 在ES6之前我们就已经在使用一种集合和箭头函数完全一样的模式了。

   function foo() {
            var self = this;
            setTimeout(function() {
                console.log(self.a)
            },100)
        }
        var obj = {
            a:2
        };
        foo.call(obj);

和箭头函数一样self = this 看起来都可以取代bind(), 但是从本质上来看,它们是想代替this这个机制。

注意

如果经常编写this风格的代码,又喜欢用箭头函数或者self= this的方法来否定this机制。
那么或许你应当:

只使用词法作用域并完全摒弃错误的this风格

完全采用this风格,在必要时仍使用bind(), 避免使用箭头函数或者self = this。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/91381.html

相关文章

  • ES6 系列之箭头函数

    摘要:回顾我们先来回顾下箭头函数的基本语法。主要区别包括没有箭头函数没有,所以需要通过查找作用域链来确定的值。箭头函数并没有方法,不能被用作构造函数,如果通过的方式调用,会报错。 回顾 我们先来回顾下箭头函数的基本语法。 ES6 增加了箭头函数: let func = value => value; 相当于: let func = function (value) { return ...

    hsluoyz 评论0 收藏0
  • es6 - 箭头函数

    摘要:也就是说箭头函数的的值不再根据调用时上下文确定,而是像普通变量那样根据定义时的作用域链进行查找。箭头函数中的依然要根据定义时的作用域链进行查找。知乎这篇文章对箭头函数的一些不适合的场景进行了总结,可以作为参考。 es6 - 箭头函数 哇,箭头函数...,听起来好NB,但是如果你知道它是因为使用了=>这样类似箭头的符号 ,所以才叫箭头函数。 瞬间感觉:呵,这名字起的...。 es6增加了...

    13651657101 评论0 收藏0
  • 箭头函数你想知道都在这里

    摘要:没有箭头函数没有自己的对象,这不一定是件坏事,因为箭头函数可以访问外围函数的对象那如果我们就是要访问箭头函数的参数呢你可以通过命名参数或者参数的形式访问参数不能通过关键字调用函数有两个内部方法和。 1、基本语法回顾 我们先来回顾下箭头函数的基本语法。ES6 增加了箭头函数: var f = v => v; // 等同于 var f = function (v) { return ...

    xiaoqibTn 评论0 收藏0
  • ES6,你不得不学!

    摘要:但是,的本质仍然是函数,是构造函数的另外一种写法。报错原生构造函数的继承对于一些原生的构造函数,比如,,,等,在是无法通过方法实现原生函数的内部属性,原生函数内部的无法绑定,内部属性获得不了。 在没有学习 ES6 之前,学习 React,真的是一件非常痛苦的事情。即使之前你对 ES5 有着很好的基础,包括闭包、函数、原型链和继承,但是 React 中已经普遍使用 ES6 的语法,包括 ...

    CKJOKER 评论0 收藏0
  • ES6学习总结(二)

    摘要:关于的学习总结昨天写了第一篇,主要是关于变量声明关键字和,新增类型以及模板字符串,今天准备写第二篇,里面的函数部分,新增了箭头函数,参数以及参数默认值。,这次我们在调用函数大的时候,两个参数全部传递了值,因此返回。 关于ES6的学习总结,昨天写了第一篇,主要是关于变量声明关键字let和const,新增类型Symbol以及模板字符串,今天准备写第二篇,ES6里面的函数部分,ES6新增了箭...

    microelec 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<