Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
zeroone001 opened this issue Apr 18, 2019 · 20 comments
Labels

Comments

@zeroone001
Copy link

No description provided.

@mengsixing
Copy link

mengsixing commented Apr 19, 2019

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

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;
}

@zaviertang
Copy link

zaviertang commented Apr 19, 2019

引入箭头函数有两个方面的作用:更简短的函数并且不绑定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
Copy link

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

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 值。

@coolliyong
Copy link

coolliyong commented Apr 19, 2019

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

箭头函数带来的好处:

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

@Caaalabash
Copy link

箭头函数不能通过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 必须是有效的)。

@Flcwl
Copy link

Flcwl commented Apr 20, 2019

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

@huijingL
Copy link

我也来献个丑:

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

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

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

@superermiao
Copy link

箭头函数与普通函数区别:
(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 函数。

@Vikingama
Copy link

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

@fireairforce
Copy link

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

@mofiggHasSugar
Copy link

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))

@spongege
Copy link

spongege commented Sep 9, 2019

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

@huatten
Copy link

huatten commented Nov 21, 2019

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

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

@Been101
Copy link

Been101 commented Jan 4, 2020

为什么不能当Generator 函数使用

@WayneGongCN
Copy link

箭头函数具有以下特性:

  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. 同样支持参数列表解构

@soraly
Copy link

soraly commented Jun 24, 2020

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

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

@Verahuan
Copy link

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

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的用意是什么呢?

@lukesyy
Copy link

lukesyy commented Nov 6, 2020

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

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

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

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

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

@Yangfan2016
Copy link

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

@MuNan-HL
Copy link

  1. 箭头函数和普通函数的区别
  • 在 JS 中, 函数亦是对象, 因此会具有自己的属性和方法. 但是 箭头函数, 只是 一种特殊的函数表达式, 是不具备 对象才具有的方法和属性的.

  • 因此, 箭头函数 没有 原型属性, 构造函数属性, 也没有 参数对象 和 this 对象.

  • 个人理解

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests