Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
javascript:新关键字在内部做什么_Javascript_Constructor_New Operator_Prototype Chain - Fatal编程技术网

javascript:新关键字在内部做什么

javascript:新关键字在内部做什么,javascript,constructor,new-operator,prototype-chain,Javascript,Constructor,New Operator,Prototype Chain,我知道可能已经有一百万个类似的问题了,例如 在这里: 在这里: 在这里: 在这里: 但请听我说完 守则: let f = function(){console.log(".f.")}; fn = new f(); // Now: typeof fn === "object" //true //! fn() //TypeError: fn is not a function //! new fn() //TypeError: fn is not a c

我知道可能已经有一百万个类似的问题了,例如

  • 在这里:
  • 在这里:
  • 在这里:
  • 在这里:
但请听我说完

守则:

let f = function(){console.log(".f.")};
fn = new f();

// Now:
typeof fn === "object" //true
//! fn() //TypeError: fn is not a function
//! new fn() //TypeError: fn is not a constructor
一般问题是:是否可以通过操作函数
f
来创建“可更新”对象
fn

这个问题细分为“新”关键字的内部

我的疑问是,根据MDN文档,当使用
new
关键字时,调用
函数
构造函数。然而,即使
fn.\uuu proto\uuu.constructor==f
与所有其他javascript
函数一样是正确的,
fn
的类型是
'object'
(我们能否以某种方式将其更改为
'function'
),并且
new fn()
抛出类型错误

我们甚至可以通过以下方式为组合添加更多内容:

fn.constructor = f.constructor 
fn.__proto__ = f.__proto__
fn.prototype = f.prototype
// f.constructor === Function //true
//! fn.call(this) //fn.call is not a function
尽管如此,
fn()
还是不起作用,
newfn
newfn()
也不起作用


为什么?

JavaScript中新的可启用对象包括:

  • 使用
    function
    关键字创建的函数(不包括生成器函数)
  • 类(可以视为函数)
  • 绑定函数外来对象(“绑定函数”)
  • 某些宿主对象
  • 代理(如果应用于上述其中一项)
  • 我知道这一点,因为只有对象类型使用(规范术语)。构造函数是具有
    [[Construct]]
    内部方法的对象,您可以搜索ECMAScript规范以找出哪些类型的对象具有
    [[Construct]]
    内部方法

    因此,要使构造函数的结果成为新的,必须返回上面列出的对象类型之一

    请注意,规范要求所有构造函数都是定义函数,因为它们必须支持
    [[Call]]
    内部方法(请注意下面关于宿主对象的警告)

    如果您想获得更高的水平,那么您可能有兴趣了解这一点(可能是出于传统Web兼容性的原因),但这些都是例外

    .constructor
    属性的说明 声明新的可启用函数
    f
    时:函数对象
    f
    本身,以及
    .prototype
    自身属性
    f
    上的默认对象。此默认
    .prototype
    对象的
    .constructor
    属性由运行时自动设置为
    f
    。我相信班级的工作方式非常相似。请注意,此属性的名称被选择为“prototype”,这一事实使得在JavaScript中讨论原型非常混乱(因为它不同于函数的
    [[prototype]]]

    位于
    .prototype
    属性上的对象上的
    构造函数
    自己的属性从未被任何内置函数或操作(据我所知)读取。我认为它在JavaScript最早的时候就已经过时了——它的初衷是作为一种方式来维护构建对象的“类”之间的链接,作为开发人员的启示。主机环境(例如浏览器)有时使用它来推断对象的“类型”,以便与用户通信(例如控制台输出),该属性是可写的,因此不可靠

    新操作员执行的步骤
    在高层,当针对构造函数调用
    new
    时,将执行以下步骤():

  • 将创建一个新对象
    o
  • o
    [[Prototype]]
    (“原型”)设置为构造函数的
    .Prototype
    属性的值(注意,这意味着
    .constructor
    属性由新对象继承)
  • 构造函数主体的目标(即
    this
    )设置为
    o
  • 构造函数使用上面定义的
    值运行
  • 如果没有显式的对象类型返回值,则默认情况下返回
    o

  • 范围:我们只在
    功能上检查
    新的
    。因为这是最让人困惑的部分。在
    Class
    上调用
    new
    会产生与其他主要OOP语言类似的结果

    原问题可分为以下两个问题:

  • 调用
    new
    关键字时,详细的构造过程是什么

  • JavaScript如何决定对象是否可调用?(感谢@BenAston提到
    新的
    关键字只能用于有限的对象集(例如,前缀为
    函数


  • 对第一个问题的答复:
  • 回到过去

    当执行代码new Foo(…)时,会发生以下情况:

  • 将创建一个新对象,继承自Foo.prototype。
  • 使用指定的参数调用构造函数Foo,并将其绑定到新创建的对象。new Foo相当于new Foo(),即如果未指定参数列表,则调用Foo时不带参数
  • 构造函数返回的对象(非null、false、3.1415或其他基元类型)成为整个新表达式的结果。如果构造函数没有显式返回对象,则将使用在步骤1中创建的对象。(通常构造函数不返回值,但如果要覆盖正常的对象创建过程,则可以选择返回值。)
  • 字眼可能模棱两可, 但PoC代码如下所示:

    //案例1,函数没有返回值;
    //将创建一个新对象f0n.\uuuu proto\uuuu===f0.prototype
    设f0=function(){};
    f0.prototype.f0p=“f0p”;
    让