Daily-Interview-Question icon indicating copy to clipboard operation
Daily-Interview-Question copied to clipboard

第 58 题:箭头函数与普通函数(function)的区别是什么?构造函数(function)可以使用 new 生成实例,那么箭头函数可以吗?为什么?

Open zeroone001 opened this issue 5 years ago • 20 comments

zeroone001 avatar Apr 18 '19 23:04 zeroone001

箭头函数是普通函数的简写,可以更优雅的定义一个函数,和普通函数相比,有以下几点差异:

1、函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。

2、不可以使用 arguments 对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

3、不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。

4、不可以使用 new 命令,因为:

  • 没有自己的 this,无法调用 call,apply。
  • 没有 prototype 属性 ,而 new 命令在执行时需要将构造函数的 prototype 赋值给新的对象的 __proto__

new 过程大致是这样的:

function newFunc(father, ...rest) {
  var result = {};
  result.__proto__ = father.prototype;
  var result2 = father.apply(result, rest);
  if (
    (typeof result2 === 'object' || typeof result2 === 'function') &&
    result2 !== null
  ) {
    return result2;
  }
  return result;
}

mengsixing avatar Apr 19 '19 00:04 mengsixing

引入箭头函数有两个方面的作用:更简短的函数并且不绑定this。箭头函数与普通函数不同之处有:

  1. 箭头函数没有 this,它会从自己的作用域链的上一层继承 this(因此无法使用 apply / call / bind 进行绑定 this 值);
  2. 不绑定 arguments,当在箭头函数中调用 aruguments 时同样会向作用域链中查询结果;
  3. 不绑定 super 和 new.target;
  4. 没有 prototype 属性,即指向 undefined;
  5. 无法使用 new 实例化对象,因为普通构造函数通过 new 实例化对象时 this 指向实例对象,而箭头函数没有 this 值,同时 箭头函数也没有 prototype。

zaviertang avatar Apr 19 '19 00:04 zaviertang

箭头函数是普通函数的简写,可以更优雅的定义一个函数,和普通函数相比,有以下几点差异:

1、函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。

2、不可以使用 arguments 对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

3、不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。

4、不可以使用 new 命令,因为:

  • 没有自己的 this,无法调用 call,apply。
  • 没有 prototype 属性 ,而 new 命令在执行时需要将构造函数的 prototype 赋值给新的对象的 proto

new 过程大致是这样的:

function newFunc(father, ...rest) {
  var result = {};
  result.__proto__ = father.prototype;
  var result2 = father.apply(result, rest);
  if (
    (typeof result2 === 'object' || typeof result2 === 'function') &&
    result2 !== null
  ) {
    return result2;
  }
  return result;
}

"函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。" 也不能说是定义时所在的对象吧,应该是定义时所在的作用域中的 this 值,因为 JS 的静态作用域的机制,this 相当于一个普通变量会向作用域链中查询结果,同时定义时所在对象也并不等于所在对象中的 this 值。

zaviertang avatar Apr 19 '19 00:04 zaviertang

区别: 1.箭头函数没有自己的this属性、arguments属性、而普通函数有,箭头函数的this指向当前函数作用域的this。 new: 2.箭头函数没有prototype显示原型,所以不能作为构造函数。

箭头函数带来的好处:

  • 没有箭头函数的时候,函数闭包 var that = this 的事没少干,有了箭头函数,就不需要这么写了。
  • 极简语法,函数式风格,写一时爽一时,一直写一直爽!

coolliyong avatar Apr 19 '19 01:04 coolliyong

箭头函数不能通过new关键字调用原因

JavaScript函数两个内部方法: [[Call]][[Construct]]

  • 直接调用时执行[[Call]]方法, 直接执行函数体

  • new调用时执行[[Construct]]方法, 创建一个实例对象blabla(如下)

function New(Ctor, ...rest) {
  const o = Object.create(Ctor.prototype)
  const ret = Ctor.apply(o, rest)
  
  return ret || o
}

箭头函数并没有[[Construct]]方法, 所以不能被用作构造函数

另外, 可以参考Proxy中的handler.construct方法

handler.construct() 方法用于拦截new操作符. 为了使new操作符在生成的Proxy对象上生效,用于初始化代理的目标对象自身必须具有[[Construct]]内部方法(即 new target 必须是有效的)。

Caaalabash avatar Apr 19 '19 01:04 Caaalabash

没有自己的this,无法指向自身。构造函数生成对象需要调用函数初始化属性。

Flcwl avatar Apr 20 '19 02:04 Flcwl

我也来献个丑:

箭头函数是ES6的写法,与function最大的不同是this的指向问题, 箭头函数内部的this 是继承自其上一级

而function 的this是看情况指向的,一般优先级是 new > bind > obj. > window new 的本质是生成一个新对象,将对象的_proto_指向函数的prototype,再执行call 方法,最后将新对象赋给定义的对象, 而箭头函数既无自己的this,也没有prototype 所以不行。

前端新手,有错误的话请不要客气,直接指出,谢谢。

huijingL avatar Apr 21 '19 07:04 huijingL

箭头函数与普通函数区别: (1)箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。例子: var person = { name: '叮当猫', sayName:function () { console.log(this.name) }, sayHi: function(){ (() => { console.log('hi') ; this.sayName() })() } } person.sayHi() // hi // 叮当猫


 var person = {
   name: '叮当猫',
   sayName:function () {
	 console.log(this.name)
	},
    sayHi: function(){
	  (function(){ console.log('hi') ;  this.sayName() })()
    }
  }
  person.sayHi()

// hi //Uncaught TypeError: this.sayName is not a function at :7:44 at Object.sayHi at :10:14 并且箭头函数的this是固定的。不是可变的。 (2)不可以当作构造函数,箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this,所以也就不能用作构造函数。 var func= ()=>{this.name = 'ss'} var personOne = new func() //VM708:2 Uncaught TypeError: func is not a constructor

(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

superermiao avatar Apr 24 '19 10:04 superermiao

剪头函数没有自己的 this,不能用作构造函数

Vikingama avatar Apr 24 '19 12:04 Vikingama

箭头函数由于this的指向在它定义的时候已经确定了(它外层代码的this),并不像其他普通函数在执行的时候确定this的指向,所以在new 的时候不会改变this的指向(在new 的过程中this会变成空对象然后指向对应的地方)

fireairforce avatar May 21 '19 16:05 fireairforce

let num1 = [1,2,2,1]; let num2 = [2,2];

let res = []; let obj = {}; function fn(n1,n2) { for(let i = 0;i<n1.length;i++){ if(!obj[n1[i]]){ obj[n1[i]] = 1; }else{ obj[n1[i]]++ } } for(let i = 0;i<n2.length;i++){ if(obj[n2[i]]){ res.push(n2[i]); obj[n2[i]]--; } } return res }

console.log(fn(num1,num2))

mofiggHasSugar avatar Jul 25 '19 10:07 mofiggHasSugar

箭头函数的this是上下文的this,它会从自己作用域的上一层继承this 箭头函数自身没有arguments(但是可以向作用域链中查找arguments), 不能使用yield命令,不能做generator函数 箭头函数不可以使用new,因为箭头函数没有prototype(使用new需要把函数的prototype赋值给新对象的__proto__),没有自己的this,不能调用call和apply

spongege avatar Sep 09 '19 08:09 spongege

  • 箭头函数语法简洁多了
  • 箭头函数没有自己的this,它里面的this指向函数所处的上下文,call和apply也没法改变this指向
  • 箭头函数没有arguments(类数组),只能基于…arg获取传递得参数集合(数组)

箭头函数不能被 new 执行,不能用作构造函数。因为箭头函数没有prototype ,也没有自己的this,不能调用call和apply

huatten avatar Nov 21 '19 10:11 huatten

为什么不能当Generator 函数使用

Been101 avatar Jan 04 '20 08:01 Been101

箭头函数具有以下特性:

  1. 没有自己的 this
    • 函数不会创建自己的 this,它只会从自己的作用域链的上一层继承 this
    • 通过 call 或 apply 调用不会改变 this 指向
    • 箭头函数不能用作构造器,和 new一起用会抛出错误
    • 所以箭头函数不适合做方法函数
  2. 没有自己的 arguments
  3. 没有自己的 super 或 new.target
    • super 关键字用于访问和调用一个对象的父对象上的函数。
    • new.target 属性允许你检测函数或构造方法是否是通过 new 运算符被调用的
  4. 箭头函数没有 prototype 属性
  5. yield 关键字通常不能在箭头函数中使用(除非是嵌套在允许使用的函数内)。因此,箭头函数不能用作函数生成器
  6. 当只有一个参数时,圆括号是可选的
  7. 加圆括号的函数体返回对象字面量表达式
  8. 支持剩余参数和默认参数
  9. 同样支持参数列表解构

WayneGongCN avatar Jan 06 '20 11:01 WayneGongCN

箭头函数与普通函数(function)的区别是什么?构造函数(function)可以使用 new 生成实例,那么箭头函数可以吗?为什么

  • 区别1,this指向的区别,function里的this会指向调用该函数的对象,箭头函数里的this是指向作用域里的this,本身没有this指向
  • 区别2,箭头函数没有arguments
  • 区别3,yield 关键字不能在箭头函数中使用
  • 箭头函数不能用new生成实例,因为箭头函数没有prototype属性,而new操作有一步是要把函数的prototype属性赋值给实例的__proto__,所以不能进行new操作

soraly avatar Jun 24 '20 09:06 soraly

箭头函数是普通函数的简写,可以更优雅的定义一个函数,和普通函数相比,有以下几点差异:

1、函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。

2、不可以使用 arguments 对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

3、不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。

4、不可以使用 new 命令,因为:

  • 没有自己的 this,无法调用 call,apply。
  • 没有 prototype 属性 ,而 new 命令在执行时需要将构造函数的 prototype 赋值给新的对象的 proto

new 过程大致是这样的:

function newFunc(father, ...rest) {
  var result = {};
  result.__proto__ = father.prototype;
  var result2 = father.apply(result, rest);
  if (
    (typeof result2 === 'object' || typeof result2 === 'function') &&
    result2 !== null
  ) {
    return result2;
  }
  return result;
}

你好,我想请问一下,后面判断result的用意是什么呢?

Verahuan avatar Jul 25 '20 15:07 Verahuan

1)、箭头函数不同于一般函数:
(1)一般函数可以先调用后定义,箭头函数只能先定义后调用

​ (2)一般函数有arguments,而箭头函数没有arguments,但可以使用rest参数(剩余参数)

​ (3)一般函数可以当作构造函数,而箭头函数不能当作构造函数,因为箭头函数没有自己的this #### 2)、箭头函数的简写形式:

(1)、当只有一个形参时可以省略圆括号;

(2)、当函数体只一条语句并且该语句会作为返回值返回时,可以省略花括号及return关键词 箭头函数中this指向依赖于外层函数中的this指向,也就是说箭头函数中的this指向定义时所在的对象,而不绑定当前调用者

lukesyy avatar Nov 06 '20 08:11 lukesyy

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions

  1. 没有自己的this ,this 指向的是最近作用域内的对象
  2. 没有 prototype,不可以进行 new 操作,没有 super,new.taret
  3. 没有 arguments 对象,但是可以使用 es6 rest 操作符 获取 所有参数
  4. 可以简写 ,如果返回值只有一句,可以省去 '{} ' 括号
  5. 不可以在 yied 中使用
  6. 绑定this 无效 call bind apply

Yangfan2016 avatar Aug 08 '22 03:08 Yangfan2016