为什么 functionName() == functionName.prototype.constructor()

why is functionName() == functionName.prototype.constructor()

我注意到我是否有以下情况:

var functionName = function(){console.log("this is a function!")}

调用functionName等同于functionName.prototype.constructor,因为它们都持有上面的函数定义。

我想我只想解释一下 JavaScript 中如何将函数用作对象,以及它与原型继承的关系。这是一个广泛的问题,所以主要是为了把它凿下来,我想知道 whywhen 函数的定义隐式设置为其构造函数.我想这与支持 new functionName() 对象构造范式有关。

why and when a function's definition is implicitly set to its constructor

这不是正在发生的事情。您误解了函数 prototype 属性.

的目的

JavaScript 中的任何函数都可以是构造函数。 “构造函数”只是一个用 new 调用的普通函数,例如 new foo().

当使用 new 调用函数时,函数 returns 一个新创建的对象,其原型链以函数的 prototype 属性 开头。对象的 __proto__ 属性(或 [[Prototype]] 内部 属性,ECMAScript 术语)设置为构造函数的 prototype 属性.

function Boat() { }
var titanic = new Boat();
console.log(titanic.__proto__ == Boat.prototype); // true

由于一个函数可以随时用作 new 的构造函数,因此每个函数都必须有一个 prototype 属性 作为构造实例的开始原型链.

实例的 constructor 属性 用于帮助该实例识别哪个构造函数创建了它。为了促进这一点,该实例有一个从其原型链继承的 constructor 属性,它被设置为从构造函数的 prototype 属性 开始。任何时候创建一个函数对象,它都会提供一个 prototype 属性,并且 prototype 属性 有一个 constructor 属性 设置为函数本身。

function Boat() { }
var titanic = new Boat();

// what constructor function made this instance? The Boat function did
console.log(titanic.constructor == Boat);

// does titanic have its own `constructor` property? no, it does not
console.log(titanic.hasOwnProperty("constructor") == false);

// the `constructor` property is inherited from the prototype chain
console.log(titanic.__proto__.constructor == Boat);

// titanic's prototype chain begins with `Boat.prototype`
console.log(titanic.__proto__ == Boat.prototype);

// these are the same
console.log(titanic.__proto__.constructor == Boat.prototype.constructor);

// these are also the same
console.log(titanic.constructor == Boat.prototype.constructor);

此行为在 ES5 13.2, Creating Function Objects、步骤 16 到 18 中描述:

  1. Create a new native ECMAScript object and let F be that object.
  2. Set all the internal methods, except for [[Get]], of F as described in 8.12.
  3. Set the [[Class]] internal property of F to "Function".
  4. Set the [[Prototype]] internal property of F to the standard built-in Function prototype object as specified in 15.3.3.1.

...

  1. Let proto be the result of creating a new object as would be constructed by the expression new Object() where Object is the standard built-in constructor with that name.
  2. Call the [[DefineOwnProperty]] internal method of proto with arguments "constructor", Property Descriptor {[[Value]]: F, ...} ...
  3. Call the [[DefineOwnProperty]] internal method of F with arguments "prototype", Property Descriptor {[[Value]]: proto, ...} ...

JavaScript 只有一种构造 - 它们是 objects。每个对象都通过其原型链接到另一个对象。当您调用函数属性时,JavaScript 将查找对象的原型、父对象的原型等,直到找到您要查找的 属性。原型搜索的最后一行类似于如果你调用 toString(),它会搜索这个,除非你已经覆盖了 toString() 属性,然后它会在 Object.prototype 中找到 toString() ].

当您声明一个函数时,解释器会创建一个新的函数对象并填充原型 属性。注意:原型的默认值是具有 属性 构造函数的对象。

function functionName() {}
var newFunction = new functionName();
newFunction.hasOwnProperty('constructor') //false
newFunction.prototype.hasOwnProperty('constructor') //true as you noted above