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”;
让