构造的用法是什么:function F() { if (!(this instanceof F)) { return new F() }; ... }
?
我在Node的pty.js
中找到了这个。这是原始代码:
function Terminal(file, args, opt) {
if (!(this instanceof Terminal)) {
return new Terminal(file, args, opt);
}
var self = this
, env
, cwd
, name
, cols
, rows
, term;
-------------------SKIP-----------------------------------
Terminal.total++;
this.socket.on('close', function() {
Terminal.total--;
self._close();
self.emit('exit', null);
});
env = null;
}
答案 0 :(得分:42)
这意味着如果在没有new
运算符的情况下调用函数,它将自动返回一个新实例。
例如,如果你没有这个保护措施,并且做了这个......
var t = Terminal();
...然后执行this
时Terminal()
将指向window
(或您的全局对象,非常喜欢的浏览器人/ gal),绝对不你想要的是什么。
通过确定this
实际上是Terminal
的实例,我们可以继续。否则,安全措施将返回一个新对象。
然后我们可以简单地使用两种形式......
var t = Terminal(); // Will be same as `new Terminal()`
答案 1 :(得分:10)
即使在没有F
的情况下调用new
,也只是为了确保它能够正常工作。
当您使用F
致电new
时,该功能this
是新实例。
然后,如果this
不是F
(!(this instanceof F)
)的实例,则表示F
未使用new
调用。在这种情况下,F
会调用自身,现在使用new
。
答案 2 :(得分:9)
除了这个主题中的重要解释之外,看看幕后发生了什么是很有趣的。 ECMAScript规范(Javascript所基于的地方)defines 全局对象。这在不同的执行环境中以不同方式实现。在典型的浏览器中,它是window
对象,而在Node.js中,它是root
对象。每个功能都定义在野外#34; (未附加到用户创建的对象)将成为全局对象的属性。在Node.js中,您可以尝试:
> function Test() {};
> root.Test
[Function: Test]
现在,this
变量指向该函数所属的对象。所以在上面的例子中:
> function Test() {
... console.log(this === root);
... };
> Test()
true
您的函数Terminal
也是如此。如果您运行它,this
将指向全局对象,当然不是Terminal
的实例!
使用new
运算符调用函数时,会返回一个对象,该对象可以访问一个名为constructor
的属性,该属性将指向该函数。它等同于:
> var instance = {};
> instance.constructor = Terminal;
> instance.constructor();
因此,当条件失败并且终端函数通过new Terminal()
行运行时,this
将指向新创建的实例,其中 类型为Terminal!< / p>
如果您想获得更多技术,instance
本身没有constructor
属性。它相反(通过原型链*)链接到私有对象**(由运行时创建),其具有指向终端函数的constructor
属性。该私有对象由函数通过prototype
属性指向返回。 D.Crockford在伪代码中显示如下:
Terminal.prototype = {constructor: Terminal};
再次,当您使用new
调用该函数时,这只是 。
*如果找不到属性,对象将在__proto__
属性指向的对象处查找。
**(想象一下名为_Terminal
的对象,你无法按名称访问)