这是我的代码:
var Person = new Function() // same as function Person(){}
var john = new Person()
现在我有这样的原型链:Object -> Function -> Person -> john
现在我正在做类似的事情:
Function.prototype.bar = "boo"
所以我希望Person.bar
和john.bar
分别是"boo"
Person.bar // boo
john.bar // undefined
那怎么了?我潜入并发现john.__proto__
是Person的原型,但是john.__proto__.__proto__
不是Function
的原型,而是Object
的原型,所以我失去了一条链条(功能)。这就是john.bar
是undefined
的原因。那么为什么会这样呢?我不能从Function
访问john
原型属性吗?
答案 0 :(得分:3)
有空的时候
var Person = new Function()
您会得到一个不执行任何操作且不返回任何内容的空函数,例如
function Person() {
}
使用new
创建Person的实例时,新创建的对象将查看Person.prototype
,并且由于Person.prototype
继承自Object
(不是{{1} }),您将看不到Function
属性。
.bar
尝试创建一个函数实例真的很奇怪,但是如果您愿意,我想您可以通过让function Person() {
}
const john = new Person();
console.log(
Object.getPrototypeOf(john) === Person.prototype,
Object.getPrototypeOf(Person.prototype) === Object.prototype
);
返回一个Person
实例来获得所需的内容:< / p>
Function
我强烈建议不要尝试创建类似这样的Function实例。
如果您想要一个(奇数)继承链
Function.prototype.bar = "boo"
function Person() {
return new Function();
};
const john = new Person();
console.log(john.bar);
然后您可以使用Object -> Function -> Person -> john
:
Object.create
答案 1 :(得分:1)
请考虑以下从this answer拍摄的图片。
如您所见,当您使用JavaScript创建函数时,也会自动创建一个新的原型对象。
function Person() {}
因此,上面的代码实际上是:
function Person() {}
Person.prototype = { constructor: Person };
现在,您还应该了解函数的__proto__
属性与其prototype
属性不同。
function Person() {}
console.log(Person.__proto__ === Function.prototype); // true
console.log(Person.prototype !== Function.prototype); // true
使用Person
关键字创建new
的实例时,该实例对象继承自Person.prototype
,而不继承自Person
或Person.__proto__
:>
function Person() {}
const john = new Person;
console.log(john.__proto__ !== Person); // true
console.log(john.__proto__ !== Person.__proto__); // true
console.log(john.__proto__ === Person.prototype); // true
通过调用new Function
创建的函数也是如此。
const Person = new Function;
console.log(Person.__proto__ === Function.prototype); // true
console.log(Person.prototype !== Function.prototype); // true
这就是john
不继承自Function.prototype
的原因。 john
的原型链如下。
__proto__ __proto__ __proto__
john -----------> Person.prototype -----------> Object.prototype -----------> null
Person
的原型链如下:
__proto__ __proto__ __proto__
Person -----------> Function.prototype -----------> Object.prototype -----------> null
这是证明:
const Person = new Function;
const john = new Person;
console.log(john.__proto__ === Person.prototype); // true
console.log(john.__proto__.__proto__ === Object.prototype); // true
console.log(john.__proto__.__proto__.__proto__ === null); // true
console.log(Person.__proto__ === Function.prototype); // true
console.log(Person.__proto__.__proto__ === Object.prototype); // true
console.log(Person.__proto__.__proto__.__proto__ === null); // true
这是因为Person.prototype !== Person.__proto__
。
现在,您可能会问为什么我们同时具有prototype
和__proto__
属性。原因是因为JavaScript中的一个对象(我们称其为derived
)仅当且仅当base
时才继承自另一个对象(我们称其为derived.__proto__ = base
)。考虑以下代码:
const base = { foo: 10 };
const derived = {};
derived.__proto__ = base; // derived now inherits from base
console.log(derived.foo); // 10
const newBase = { bar: 20 };
derived.__proto__ = newBase; // derived no longer inherits from base, it inherits from newBase
console.log(derived.foo); // undefined
console.log(derived.bar); // 20
现在,当您创建函数的实例时,该实例实际上是从函数的prototype
继承的。它不是从函数继承的。
function Person() {}
const john = new Person;
上面的代码等效于:
function Person() {}
Person.prototype = { constructor: Person };
const john = { __proto__: Person.prototype };
Person.call(john);
希望能清除一切。