美文网首页
箭头函数

箭头函数

作者: 李幸娟 | 来源:发表于2020-03-06 18:20 被阅读0次

[TOC]

箭头函数之前不常用的语法

直接返回一个对象

let func = (value, num) => ({ data: value + num });
func(1, 2); // { data :3 }

与变量解构

let func = ({ value, num }) => ({ data: value + num });
console.log(func({ value: 1, num: 2 })); // { data :3 }

与变量解构的应用(在react中)

一般设置state的方式


state = {
  data: {
    age: 17
  }
};

handleSet = () => {
  this.setState({
    data: this.state.data.set("key", "value")
  });
};

使用箭头函数与变量解构后可以简化为


handleSet2 = () => {
  this.setState(({ data }) => ({
    data: data.set("key", "value")
  }));
};

没有this

  • 箭头函数需要查找作用域链来确定this的值

  • 这就意味着如果箭头函数被非箭头函数包含,this绑定的就是最近一层非箭头函数的this

  • 下面这个例子,箭头函数中的this绑定的就是他的外层函数demo()的this,而demo()是在全局作用域中调用的,所以这个this, 指向的是全局作用域window

var value = 2;
function demo() {
  const value = 1;
  const b = () => {
    console.log(this);
  };
  b();
}
demo(); // 2

因为箭头函数没有this,所以不能使用call(), apply(), bind()这些方法改变this的指向

var name = "hong";
const person = {
  name: "ming"
};
function sayName() {
  return this.name;
}
const sayName2 = () => {
  return this.name;
};
console.log(sayName());             // "hong"
console.log(sayName.call(person));  // "ming"
console.log(sayName2());            // "hong" => this始终指向window 
console.log(sayName2.call(person)); // "hong" => this始终指向window 

箭头函数没有this,给我们带来了很多方便,比如之前我们希望函数内部的闭包可以拿到他的包含作用的this, 就需要提前将this保存在一个闭包可以放到的变量里面;
在匿名函数返回之前,我们将sayName()的this(指向obj)保存在变量that中,这样,我们就可以通过that访问到obj的name属性

function Person() {
  var that = this;
  that.age = 0;

  setTimeout(function() {
    console.log(that.age); // |this| 正确地指向 p 实例
  }, 1000);
}

var p = new Person();  // 0

但是由于箭头根本没有this,所以可以直接访问包含函数this

function Person() {
  this.age = 0;

  setTimeout(function() {
    console.log(this.age); // |this| 正确地指向 p 实例
  }, 1000);
}

var p = new Person(); // 0

this和arguments也存在着同样的问题。如果不使用箭头函数,但是想访问作用域中的arguments对象,必须将对该对象的引用保存到另一个闭包能够访问的变量中。

没有arguments

箭头函数没有自己的arguments对象,这不一定是一件坏事,因为这样,箭头函数就可以访问外围函数的arguments对象

如果你非要使用arguments对象怎么办呢

const demo = (...args) => {
  return args;
};
demo(1, 2, 3);  // [1, 2, 3] 

在函数柯里化的时候就很方便了,正常情况下我们需要吧外层函数的除了第一个参数外的参数与内部的参数拼接起来,如下

const add = function(a, b, c, d) {
  return a + b + c + d;
};
function curry(fn) {
  const args = Array.prototype.slice.call(arguments, 1);
  return function() {
-   const innerArgs = Array.prototype.slice.call(arguments);
    const finalArgs = [...args, ...innerArgs];
    return fn.apply(null, finalArgs);
  };
}
console.log(curry(add, 1)(2, 3, 4));  // 10

由于箭头函数没有arguments对象的特性,我们就可以直接访问他的包含函数的arguments对象,函数柯里化我们可以写成这个样子

function curry(fn) {
  return (..._args) => {
    const finalArgs = [...[].slice.call(arguments, 1), ..._args];
    return fn.apply(null, finalArgs);
  };
}
console.log(curry(add, 1)(2, 3, 4));  // 10

没有new.target属性(即不能通过new关键字调用)

普通的函数调用中(和作为构造函数来调用相对),new.target 的值是undefined;而在构造函数中调用时,new.target指向被new调用的构造函数这使得你可以检测一个函数是否是作为构造函数通过new被调用的

function Demo() {
  console.log(new.target === window.Demo);
}
new Demo();  // true
  • 这里冴羽的博客说函数有[[call]]和[[constructor]], 当通过new 调用函数时,执行 [[Construct]] 方法,创建一个实例对象,然后再执行函数体,将 this 绑定到实例上; 当直接调用的时候,执行 [[Call]] 方法,直接执行函数体。
  • 箭头函数没有[[Construct]]方法,所以不能被用作构造函数,所以通过new的方式调用会报错
  • 但是我没有看到书上有介绍过 [[Call]] 方法,等我找到回来改

把箭头当作构造函数,使用new创建的实例报错

const Demo = () => {console.log(1)};
const demo1 = new Demo(); // TypeError: Demo is not a constructor

没有原型

箭头函数不存在prototype这个属性

const DemoA = () => {
  console.log(1);
};

const DemoB = function() {
  console.log(1);
};
console.log(DemoA.prototype.constructor === DemoA); // TypeError: Cannot read property 'constructor' of undefined
console.log(DemoB.prototype.constructor === DemoB); // true

避免使用箭头函数的三种情况

由于箭头函数没有绑定this, 所以以下三种情况避免使用

  1. 对象的方法
// bad
const person = {
  name: "小红",
  sayName: () => {
    console.log(this);  // Window
    return this.name
  }
};
person.sayName();
person.sayName();   // undefined

  1. 定义原型方法
// right
function FooA() {
  this.value = 1;
}
FooA.prototype.getValue = function() {
  console.log(this);  // 指向FooA的实例
  console.log(this.value);
};

let foo1 = new FooA()
let foo2 = new FooA()
foo2.value = 2

foo1.getValue() // 1
foo2.getValue() // 2

// bad
function Foo() {
  this.value = 1
}

Foo.prototype.getValue = () => {
  console.log(this) // Window
  console.log(this.value)
}

let foo = new Foo()
foo.getValue();  // undefined
  1. 作为事件的回调函数
// bad
const button = document.getElementById('myButton');
button.addEventListener('click', () => {
    console.log(this === window); // => true
    this.innerHTML = 'Clicked button';
});

参考

相关文章

  • ES6~箭头函数

    什么是箭头函数 单表达式箭头函数 相当于 多表达式箭头函数 箭头函数相当于匿名函数,并且简化了函数定义。箭头函数有...

  • 箭头函数和立即执行函数

    箭头函数 箭头函数和普通函数有什么区别?如果把箭头函数转换为不用箭头函数的形式,如何转换主要是this的差别,箭头...

  • 学习 ES 6 箭头函数

    箭头函数的用法 ES6 允许使用“箭头”(=>)定义函数。 箭头函数的一个用处是简化回调函数。 箭头函数 this...

  • 箭头函数

    箭头函数 箭头函数能让this的指向固定化 分析:1)第一个setInterval()中使用了箭头函数,箭头函数使...

  • TS  笔记this

    this 箭头函数在箭头函数创建的地方获得this;非箭头函数,在调用函数的地方获得this如图

  • 箭头函数和数组

    箭头函数&数组 箭头函数 特点: 没有 this 没有 arguments 没有prototype在箭头函数中使用...

  • 箭头函数

    箭头函数 为什么使用箭头函数

  • 箭头函数中this的指向

    箭头函数在平时开发中用着非常爽,箭头函数有什么特点呢 箭头函数不能够当做构造函数使用 箭头函数没有argument...

  • js学习笔记4(函数)

    1.箭头函数 ES6新增属性。箭头函数特别适合嵌入函数的场景。 箭头函数虽然语法简介,但是很多场合不适用。箭头函数...

  • js理解普通函数和箭头函数

    普通函数: 箭头函数: 区别: 构造函数和原型 箭头函数不能作为构造函数 不能new。会报错 箭头函数没有原型属性...

网友评论

      本文标题:箭头函数

      本文链接:https://www.haomeiwen.com/subject/bvawrhtx.html