Skip to content
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

Day7 - 分析一下箭头语法为什么不能当做构造函数 #25

Open
su37josephxia opened this issue Jan 6, 2022 · 43 comments
Open

Comments

@su37josephxia
Copy link
Owner

su37josephxia commented Jan 6, 2022

@ruixue0702
Copy link

箭头函数中的this指向上一层级的作用域,构造函数中的this指向当前函数的作用域,两者间的this指向不同,所以箭头函数是不能够作为构造函数的

@bianzheCN
Copy link

因为箭头函数没有自己的 this

@qzyqzy
Copy link

qzyqzy commented Jan 7, 2022

分析一下箭头语法为什么不能当做构造函数

更正答案:
是因为箭头函数没有 [[Construct]] 。如果通过new调用,就会出错

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

  let Animal = () => {};
  console.log(Animal.prototype); // undefined

注意点:

  • 箭头函数没有自己的 this,而是继承父作用域的 this
  • 不支持 call bind,改变 this 指向。
  • 不绑定 arguments
  • 没有 prototype 属性

@rachern
Copy link

rachern commented Jan 7, 2022

箭头函数的 this 是在定义是就确定的,用的是父作用域的 this,其本身没有 this
箭头函数也没有 prototype
构造函数在使用 new 生成实例时,会产生一个空对象,将构造函数的 this 指向这个空对象,而箭头函数没有自己的 this,所以无法把 this 指向这个空对象
生成实例的过程中,会把空对象的 __proto__ 指向构造函数的 prototype,而箭头函数中没有 prototype,所以这也是箭头函数不能当做构造函数的原因

@MMmaXingXing
Copy link

主要原因是因为性质问题,箭头函数的this指向的是全局对象,构造函数模式创建的this对象需要指向当前的对象。

箭头函数没有prototype。

构造函数模式在生成的时候主要依赖于原型继承链来关联相关的关系,而箭头函数没有,因此不行。

@BambooSword
Copy link

  1. MDN文档指出:箭头函数的this是指向更外层的scope的(Lexical this), new 无法使用箭头函数来 construct 对象。
  2. ECMA Spec:想要对某个对象使用 new, 需要保证该对象 具有[[Construct]]这个内部方法,而箭头函数没有。

@Colin3191
Copy link

箭头函数在其他语言里叫做lambda表达式,是一种函数式编程风格,而new是一种面向对象的编程风格。所以箭头函数不支持new调用也显得比较合理。

@partiallove
Copy link

分析一下箭头语法为什么不能当做构造函

  • 没有单独的this
  • 不绑定arguments
  • 箭头函数不能用作构造器,和 new一起用会抛出错误
  • 箭头函数没有prototype属性

@alec1815
Copy link

alec1815 commented Jan 7, 2022

箭头函数本身没有this,因此不能使用箭头作为构造函数,也就不能通过 new 操作符来调用箭头函数。

@wzl624
Copy link

wzl624 commented Jan 7, 2022

构造函数是通过new关键字来生成对象实例,生成对象实例的过程也是通过构造函数给实例绑定this的过程,而箭头函数没有自己的this。创建对象过程,new 首先会创建一个空对象,并将这个空对象的__proto__指向构造函数的prototype,从而继承原型上的方法,但是箭头函数没有prototype。因此不能使用箭头作为构造函数,也就不能通过new操作符来调用箭头函数。

@qytayh
Copy link

qytayh commented Jan 7, 2022

结论

js里面每个非箭头函数都有两个内部方法,一个是[[call]],另一个是[[construct]],在不是用new进行调用函数时,函数会调用内部的[[call]]方法,而使用new调用时,函数会调用内部的[[construct]]方法

对于箭头函数来说,箭头函数是没有[[construct]]的内部方法的,这个才是箭头函数不能作为构造函数的真正原因

引申

箭头函数中的this、super、arguments及new.target这些值由外围最近一层非箭头函数决定

因为不能通过new关键字调用,没有构造原型的需求,所以箭头函数不存在prototype属性

箭头函数没有自己的arguments对象,它始终可以访问外围函数的arguments对象

@792472461
Copy link

箭头函数的 this 是在定义是就确定的,用的是父作用域的 this,其本身没有 this
箭头函数也没有 prototype
构造函数在使用 new 生成实例时,会产生一个空对象,将构造函数的 this 指向这个空对象,而箭头函数没有自己的 this,所以无法把 this 指向这个空对象
生成实例的过程中,会把空对象的 proto 指向构造函数的 prototype,而箭头函数中没有 prototype,所以这也是箭头函数不能当做构造函数的原因

@674252256
Copy link

在使用function定义函数时,可以在函数内部访问arguments对象,从中取得传进来的每个参数值,如果函数是使用箭头函数定义的,那么传给函数的参数不能使用arguments关键字访问,而只能通过定义的命名参数访问

@chunhuigao
Copy link

  • 箭头函数没有自己的this
  • 使用new生成实例的时候,需要将构造函数this绑定发实例上,但是箭头函数没有自己的this
  • 所以箭头函数不能用作构造函数

@674252256
Copy link

在使用function定义函数时,可以在函数内部访问arguments对象,从中取得传进来的每个参数值,如果函数是使用箭头函数定义的,那么传给函数的参数不能使用arguments关键字访问,而只能通过定义的命名参数访问

@8023nana
Copy link

8023nana commented Jan 7, 2022

首先箭头函数没有自己的this,而是继承父作用域的this。
构造函数是通过是通过new关键字来生成实例对象,生成实例对象的过程也是通过构造函数给实例绑定this的过程,而箭头函数没有自己的this。所以箭头函数不能当作构造函数使用

@bianxuerui
Copy link

1.在箭头函数中,this指向的是定义时所在的对象,而不是使用时所在的对象。换句话说,箭头函数没有自己的this,而是继承父作用域中的this。

2.创建对象过程,new 首先会创建一个空对象,并将这个空对象的__proto__指向构造函数的prototype,从而继承原型上的方法,但是箭头函数没有prototype。因此不能使用箭头作为构造函数,也就不能通过new操作符来调用箭头函数。

@jj56313751
Copy link

jj56313751 commented Jan 7, 2022

  • new一个实例需要函数内部有[[Construct]]内部方法,箭头函数没有这个内部方法
  • 构造函数将this指向实例,箭头函数的this穿透本层指向上一层的作用域

@Limeijuan
Copy link

为什么箭头函数不能当做构造函数?
因为箭头函数没有自己的this,也没有prototype属性;
构造函数是通过new关键字来生成对象实例,生成对象实例的过程也是通过构造函数给实例绑定this的过程,而箭头函数没有自己的this。创建对象过程,new 首先会创建一个空对象,并将这个空对象的__proto__指向构造函数的prototype,从而继承原型上的方法,但是箭头函数没有prototype。因此不能使用箭头作为构造函数,也就不能通过new操作符来调用箭头函数。

@zcma11
Copy link

zcma11 commented Jan 7, 2022

new 构造函数的时候会将 this 绑定为生成的实例对象,但是箭头函数没有自己的 this,是引用的外部的 this,就连 bind, call 这些也没办法修改 this,那 new 自然也没办法修改。所以就无法作为构造函数。假设真的构造了,变量就都存到外面的 this去了。返回的实例也是外面的this。

@superjunjin
Copy link

  • this一般指向函数的调用者。但是在箭头函数中,this指向的是定义时所在的对象,而不是使用时所在的对象。

  • 换句话说,箭头函数没有自己的this,而是继承父作用域中的this。

  • 普通构造函数生成实例的过程如下

function Person(name,age){
  this.name = name
  this.age = age
}
var p = new Person('张三',18)
  • new关键字生成实例过程

    1. 创建空对象p

      var p = {}

    2. 将空对象p的原型链指向构造器Person的原型

      p.__proto__ = Person.prototype

    3. 将Person()函数中的this指向p

      Person.call(p)

  • 若此处Person为箭头函数,则构造函数没有自己的this。call()函数无法改变箭头函数的指向,也就无法指向p。

所以箭头函数不能做构造函数

@QbjGKNick
Copy link

什么是箭头函数
箭头函数是匿名函数,它没有this、arguments、super以及new.target,箭头函数不会创建自己的this,只会从自己的作用域链上一层继承this。

@Theseus-Xin
Copy link

实际上,js里面每个非箭头函数都有两个内部方法,一个是[[call]],另一个是[[construct]],在不是用new进行调用函数时,函数会调用内部的[[call]]方法,而使用new调用时,函数会调用内部的[[construct]]方法。

@863379105
Copy link

@yaoqq632319345
Copy link

当new一个构造函数,首先需要创建一个对象,然后修改this指向新创建的对象,再把构造函数的prototype属性赋值给新创建对象的__proto__
而箭头函数在定义时他的this就确定了,且不能使用bind,call,apply来修改this,还有箭头函数没有prototype属性,所以在new时会抛出错误

@oujinlong
Copy link

不能
1.没有内部 this 指向
2.没有 construct 方法,所以不能被 new关键字调用

@JanusJiang1
Copy link

JanusJiang1 commented Jan 7, 2022

箭头函数为什么不能作为构造函数?

因为箭头函数不具备作为一个构造函数,能通过new去创建实例的必备条件。箭头函数没有prototype,也没有自己的this,是引用的上层非箭头函数的this,也不能通过call,aply改变this指向。

我们在new一个实例的时候,会发生以下几步:

  • 创建一个新对象,并把函数内的this指向改绑定到该对象

  • 还会把这个对象的_proto_绑定函数的prototype,以继承函数原型上的属性,方法。

而前面也说过构造函数既没有prototype也不能改变this指向,所以不能完成实例化过程 ,自然也不能作为构造函数。

@bubucuo
Copy link

bubucuo commented Jan 7, 2022

构造函数调用需要一个prototype属性,而箭头函数定义的函数没有prototype属性,因此不能作为构造函数使用。而且,箭头函数中的this是从定义它们的上下文继承的,不会根据调用它们的对象来动态设置。这样定义的方法就不能用了,因为方法的典型特点就是使用this引用调用它们的实例。
好在ES6新增的类语法不允许使用箭头函数定义方法,因此在使用该语法时候不必担心自己会意外犯这种错误。
---来自犀牛书P206&208。
---多读书,网上很多资料五花八门,筛选有效信息很费时,翻书才是最有效的学习途径。

@Tiffany-yuan
Copy link

箭头函数不能用做构造函数,是因为new会创建一个空对象,并将这个空对象的_proto_指向构造函数的prototype,从而继承原型上的方法,但是箭头函数没有prototype,所以箭头函数不能用做构造函数。
而且在箭头函数没有自己的this,它的this是继承父作用域中的this。call()、apply()、bind()的作用是改变函数的this指向,但是箭头函数没有自己的this,不支持这些函数的特性。

@yl-code
Copy link

yl-code commented Jan 7, 2022

@attackam
Copy link

attackam commented Jan 7, 2022

本质原因,缺少[construct]方法

构造函数生来就是被new的, 如果不new它将毫无意义。那么就回到了我们上次new会发生什么事情。其中this的指向固然是丢失的,但是不影响程序的运行,顶多数据混乱了。其次constructor方法被调用,这一步会报错,也就不会往下执行了,不能被new,所以箭头函数也无需拥有prototype属性。

@yanzefeng
Copy link

箭头函数不能用作构造函数是因为,箭头函数创建的时候不会为其创建[[construct]]方法,意味着没有构造能力,所以自然不能调用new来生成实例,所以箭头函数的prototype属性也没有必要存在了。

  • 延伸箭头函数和普通函数的区别
new和原型 arguments this指向 call,apply,bind
普通函数 动态 修改this值
箭头函数 没有 没有 一般是window
被普通函数包含指向上一层
不可修改this值

@xyz-fish
Copy link

xyz-fish commented Jan 7, 2022

箭头函数为什么不能new

首先new运算符 是 创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例

然后 箭头函数 没有内部[[Construct]] 这个构造器方法,所以不能new


  1. js对象 都是构造函数生成的 new Object() new Function() 也包含new Number()那三个特殊的
  2. 箭头函数应该只是是es6新的语法糖, 在我们书写箭头函数时候 也不能出现() =>换行的情况,他就像一个表达式返回了一个特殊的函数, 所以他没有prototype 不像普通函数那样含有构造器
  3. 在预解析的阶段 ,他们的处理方式也是不一样的,普通函数就像我们所说的有自己的作用域 执行时完善的作用域链,而箭头函数作用域的对象是指向他所处的一个作用域的对象,执行时的作用域链也就指向了所处的作用域 这也导致了this 指向的问题 和 arguments的问题, 以及在使用call apply的一些问题
  4. 在箭头函数执行的时候 如果 new.target 也会报错

@zzzz-bang
Copy link

1、this指向的是定义时所在的对象。换句话说,箭头函数没有自己的this,而是继承父作用域中的this
2、不支持call()/apply()函数特性
3、不绑定arguments
4、没有prototype属性

@liangle
Copy link

liangle commented Jan 7, 2022

因为箭头函数的 [[thisMode]] 私有属性是 lexical,表示从上下文中找 this 值,如果箭头函数当构造函数,实例化的对象内部的函数调用时的 this 值不会指向该对象,所以不能做构造函数。

@zhenyuWang
Copy link

一句话答案

因为箭头函数没有 [[Construct]]。

进一步解释

函数对象是一个支持[[Call]] 、 [[Construct]]内部方法的对象。每个支持[[Construct]]的对象必须支持[[Call]],也就是说,每个构造函数必须是一个函数对象。因此,构造函数也可以被称为 构造函数函数构造函数对象
所以,想要对某个对象使用 new,就得确保该对象具有 [[Construct]] 这个内部方法。而箭头函数没有 [[Construct]]。

为什么没有 [[Construct]]

因为箭头函数设计之初,就是为了设计一种更简短的函数并且不绑定 this。所以箭头函数不为参数 superthisnew.target 定义本地绑定。箭头函数中的 thissuperargumentsnew.target 这些值由外围最近一层非箭头函数决定。

而这样的一个函数设计者认为没有必要委托给能够 [[Construct]] 的目标函数。所以箭头函数没有 [[Construct]]。
同时因为没有构造原型的需求,所以箭头函数不存在 prototype 属性。

@jiafei-cat
Copy link

箭头函数不能当做构造函数的原因

  • 因为箭头函数特性,this总是指向外层非箭头函数作用域的this, 无法通过call bind apply改变this指向, 在new的时候无法动态设置绑定新对象为构造函数的this
  • 为了防止箭头函数被作为构造函数,所以箭头函数没有[[Construct]]内部方法, 自然无法被new, 所以也没有prototype
  • 没有arguments

@rhythm022
Copy link

rhythm022 commented Jan 7, 2022

构造函数调用的过程中会创建新的对象,并且把函数的prototype属性设置为新对象的原型。

箭头函数它本身是没有prototype属性的,这是一方面。第二个方面,箭头函数也没有本地的this用来创建新对象。所以,箭头函数既没有新对象又没有原型,这两大对于构造函数最重要的特征,那么因此,他就没有办法用来当作构造函数。

@crazyyoung1020
Copy link

箭头函数不能用作构造函数,与new一起使用会报错。

箭头函数有以下特点:

  1. 没有caller,也就没有自己的this,箭头函数中的this是自身所处的上下文的this
  2. 没有arguments
  3. 没有prototype

那么假设我们new一个箭头函数,我们会面临几个问题

  1. 无法绑定arguments
  2. 由于箭头函数没有prototype,所以无法将新创建的空对象的__proto__指向构造函数的prototype
  3. 由于箭头函数没有自己的this,我们没办法用call或apply去改变构造函数this的指向

@aiuluna
Copy link

aiuluna commented Jan 7, 2022

  • 箭头函数没有constructors属性,没有构造器的函数无法构建实例
  • 箭头函数没有prototype,所以无法将新创建的空对象的__proto__指向构造函数的prototype
  • 箭头函数中的this是从定义它们的上下文继承的,不会从创建的实例去动态改变他的引用,而正常定义实例对象的方法执行就是依靠改变构造函数this指向实例对象。

@alienRidingCat
Copy link

alienRidingCat commented Jan 7, 2022

构造函数是通过new关键字来生成实例对象,将一个空对象的__proto__指向构造函数的prototype,但是箭头函数没有prototype属性,所以不能作为构造函数调用;另外生成对象实例的过程也是通过构造函数给实例绑定this的过程,而箭头函数也没有自己的this,如果new关键字生成箭头函数的实例对象,这是行不通的

@guoshukun1994
Copy link

如果箭头函数想要当构造函数,那它必须得能够通过new操作符调用生成一个实例化新对象,这种调用过程在新对象内部的原型指针赋值为构造函数的prototype属性,而箭头函数本身是没有prototype属性的,如下 image

第二个,new实例化过程中需要通过构造函数的构造方法给新对象绑定属性方法,而箭头函数是没有构造器的

@wangyfax
Copy link

wangyfax commented Jan 8, 2022

构造函数是通过new关键字来生成实例对象,将一个空对象的__proto__指向构造函数的prototype,但是箭头函数没有prototype属性,所以不能作为构造函数调用;另外生成对象实例的过程也是通过构造函数给实例绑定this的过程,而箭头函数也没有自己的this,所以不能用new关键字生成箭头函数的实例对象

@su37josephxia su37josephxia changed the title 分析一下箭头语法为什么不能当做构造函数 Day7 - 分析一下箭头语法为什么不能当做构造函数 Jan 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests