javascript|[[Prototype]] ——原型链两万字全面解析「建议收藏」( 六 )


「构造函数」回到之前的代码:
function Foo() {    var a = new Foo();
到底是什么让我们认为 Foo 是一个「类」呢?
其中一个原因是我们看到了关键字 new , 在面向对象类的语言中构造类实例时也会用到它 。 另一个原因是 , 看起来我们执行了类构造函数方法 , Foo() 的调用方式很像初始化类构造函数的调用方式 。


使用了关键字 new , 以及类似于构造函数一样的调用 。 让 Foo 看起来像是一个类 。
令人迷惑的「构造函数」语义外 , Foo.prototype 还有另一个绝招 。 思考下面的代码:
function Foo() {    Foo.prototype.constructor === Foo // truevar a = new Foo()a.constructor === Foo // true
Foo.prototype 默认有一个公认并且不可枚举的属性 constructor , 这个属性引用的是对象关联函数 , 本例中是 Foo 。 此外 , 我们可以看到通过「构造函数」调用 new Foo() 创建的对象也有一个 construotor 属性

Foo.prototype.constructor 不可枚举 , 引用的是对象关联对象 , 也据是原型前面的对象 , 也就是自身 。
按照 JavaScript 世界的惯例 , 「类」名首字母要大写 , 所以名字写作 Foo 而非 foo 似乎也提示它是一个「类」 。 显而易见 , 是吧?
构造函数还是调用上一段代码很容易让人认为 Foo 是一个构造函数 , 因为我们使用 new 来调用它并且看到它的「构造」了一个对象 。
实际上 , Foo 和你程序中的其他函数没有任何区别 。 函数本身并不是构造函数 , 然而 , 当你在普通的函数前面加上 new 关联字之后 , 就会把这个函数变成一个「构造函数调用」 。 实际上 , new 会劫持所有普通函数并用构造对象的形式来调用它 。

Foo 函数只是一个普通的函数 , 特殊之处在于 new 关键字的行为 。
new 关键字会以构造对象的形式来调用函数 。
function Nothing() {  console.log('i feel busy')var a = new Nothing() // 'i feel busy'a // Nothing { ___proto___: { constructor: ? Nothing()  
Nothing 只是一个普通的函数 , 但是使用 new 调用时 , 它就会构造一个对象并赋值给 a , 这看起来是 new 的一个副作用 。 这个调用是一个构造函数调用 , 但是 Nothing 本身并不是一个构造函数 。

这里提到了一个概念:构造函数调用 。
在 JavaScript 中并没有构造函数 , 只有以构造函数方式调用 。
换句话说 , 在 JavaScript 中对于「构造函数」最准确的解释是 , 所有带 new 的函数调用 。
函数不是构造函数 , 但是当且仅当使用 new 时 , 函数调用会变成「构造函数调用」 。
技术我们是不是已经介绍了 JavaScript 中所有和「类」相关的问题了呢?
不是 , JavaScript 开发者绞尽脑汁想要模仿类:
function Foo(name){  this.name = nameFoo.prototype.myName = function() {  return this.namevar a = new Foo('foo')var b = new Foo('bar')a.name // 'foo'b.name // 'bar'a // Foo { name: 'foo' ___proto___: { constructor: ? Foo() myName: ? ()  
这段代码展示了另外两种「面向类」的技巧: