为什么 functionName() == functionName.prototype.constructor()
why is functionName() == functionName.prototype.constructor()
我注意到我是否有以下情况:
var functionName = function(){console.log("this is a function!")}
调用functionName
等同于functionName.prototype.constructor
,因为它们都持有上面的函数定义。
我想我只想解释一下 JavaScript 中如何将函数用作对象,以及它与原型继承的关系。这是一个广泛的问题,所以主要是为了把它凿下来,我想知道 why 和 when 函数的定义隐式设置为其构造函数.我想这与支持 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 中描述:
- Create a new native ECMAScript object and let F be that object.
- Set all the internal methods, except for [[Get]], of F as described in 8.12.
- Set the [[Class]] internal property of F to "
Function
".
- Set the [[Prototype]] internal property of F to the standard built-in Function prototype object as specified in 15.3.3.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.
- Call the [[DefineOwnProperty]] internal method of proto with arguments "
constructor
", Property Descriptor {[[Value]]: F, ...} ...
- 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
我注意到我是否有以下情况:
var functionName = function(){console.log("this is a function!")}
调用functionName
等同于functionName.prototype.constructor
,因为它们都持有上面的函数定义。
我想我只想解释一下 JavaScript 中如何将函数用作对象,以及它与原型继承的关系。这是一个广泛的问题,所以主要是为了把它凿下来,我想知道 why 和 when 函数的定义隐式设置为其构造函数.我想这与支持 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 中描述:
- Create a new native ECMAScript object and let F be that object.
- Set all the internal methods, except for [[Get]], of F as described in 8.12.
- Set the [[Class]] internal property of F to "
Function
".- Set the [[Prototype]] internal property of F to the standard built-in Function prototype object as specified in 15.3.3.1.
...
- Let proto be the result of creating a new object as would be constructed by the expression
new Object()
whereObject
is the standard built-in constructor with that name.- Call the [[DefineOwnProperty]] internal method of proto with arguments "
constructor
", Property Descriptor {[[Value]]: F, ...} ...- 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