假设我有这段代码:
// Male will inherit ALL of the Human properties
function Human(x, y) {
// Following properties will be inherited
this.name = x;
this.age = y;
this.test = "Test 1";
}
// Following properties will ALSO be inherited
Human.prototype.citizen = "USA";
Human.prototype.employer = "Google";
Human.prototype.test = "Test 2";
function Male(x, y) {
// Following properties will be the own properties of Male instances
this.name = x;
this.age = y;
this.gender = "Male";
}
// Inheritance - Connecting Male object with Human object
Male.prototype = new Human(); // no arguments are passed
Male.prototype.constructor = Male; // correcting constructor property
var albert = new Male("Albert", 25);
然后,我想对代码进行一些测试
Human.isPrototypeOf(albert); // I expect it to return TRUE
但它返回FALSE,为什么会这样?
并且,对于以下测试
Human.hasOwnProperty("age"); // /i expect it to return TRUE
但它返回FALSE,为什么会这样?
谢谢,
修改 我的问题与另一个问题略有不同,因为它也讨论了原型链。
答案 0 :(得分:7)
Human
原型链中albert
函数不是。 Human.prototype
引用的对象是:
Human.prototype.isPrototypeOf(albert); // true
Human.hasOwnProperty( “年龄”); //我希望它返回TRUE
Human
函数没有age
属性。由new
创建的实例执行:
new Human().hasOwnProperty("age"); // true
旁注:您设置继承链的方式很常见,并在很多示例中显示,但在两个方面不正确:
您不想使用new Human
来创建Male.prototype
。
您做想要从Human
致电Male
:
所以:
function Male(x, y) {
// Give Human its chance to initialize the object (#2)
Human.call(this, x, y);
// ...
}
// Don't use new Human to create the prototype (#1)
Male.prototype = Object.create(Human.prototype);
Male.prototype.constructor = Male;
您不使用new Human
为Male
创建原型的原因很简单:Human
需要参数,但您无需提供参数。
这是更新的ES5及该代码的早期版本:
function Human(name, age) { // Argument names should be meaningful
this.name = name;
this.age = age;
this.test = "Test 1";
}
Human.prototype.citizen = "USA";
Human.prototype.employer = "Google";
Human.prototype.test = "Test 2";
function Male(name, age) {
Human.call(this, name, age);
this.gender = "Male";
}
Male.prototype = Object.create(Human.prototype);
Male.prototype.constructor = Male;
var albert = new Male("Albert", 25);
console.log(Human.prototype.isPrototypeOf(albert)); // true
console.log(new Human().hasOwnProperty("age")); // true
当然,也可以使用ES2015 +(如果您的目标尚不支持,请进行转换):
// THIS SNIPPET REQUIRES A BROWSER WITH ES2015+ SUPPORT
class Human {
constructor(name, age) {
this.name = name;
this.age = age;
this.test = "Test 1";
}
}
Human.prototype.citizen = "USA";
Human.prototype.employer = "Google";
Human.prototype.test = "Test 2";
class Male extends Human {
constructor(name, age) {
super(name, age);
this.gender = "Male";
}
}
let albert = new Male("Albert", 25);
console.log(Human.prototype.isPrototypeOf(albert)); // true
console.log(new Human().hasOwnProperty("age")); // true
你说过你正试图看看连锁店是如何运作的。以下是创建albert
后我们在内存中的图表(为简单起见,删除了一些详细信息):
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ | | \ +−−−−−−−−−−−−−−−−+ | Human−−−−−>| function | | +−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−+ | | prototype |−−−−−−−−−−−−−−−−−−−−−−−−−−−>| object | | | name: "Human" | / +−−−−−−−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−+ | | constructor |−+ | | citizen: "USA" | +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ | | employer: "Google" | | | | | test: "Test 2" | \ +−−−−−−−−−−−−−−−−+ | | +−−−−−−−−−−−−−−−−−−−−+ Male−−−−−−>| function | | | +−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−+ | | | prototype |−−−>| object | | | | name: "Male" | / +−−−−−−−−−−−−−−−−−+ | | +−−−−−−−−−−−−−−−−+ | | constructor |−+ | | | [[Prototype]] |−−−+ +−−−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−−+ albert−−−−>| object | | +−−−−−−−−−−−−−−−−+ | | name: "Albert" | | | age: 25 | | | gender: "Male" | | | [[Prototype]] |−−+ +−−−−−−−−−−−−−−−−+上面的
[[Prototype]]
是规范用于包含对其原型对象的引用的对象的“内部槽”的名称。相比之下,prototype
,函数上的属性(例如,Human.prototype
),只是函数的正常属性,指向new
将用作[[Prototype]]
的对象如果将该函数与new
一起使用,则会创建新对象。
该图表上的一些注释:
[[Prototype]]
内部插槽,指向对象Function.prototype
指向(为简单起见,上面省略)。Human
,该函数具有name
属性:"Human"
Male
,该函数具有name
属性:"Male"
albert
引用的属性为name
:"Albert"
albert
的{{1}}是[[Prototype]]
; Male.prototype
的{{1}}是Male.prototype
(而[[Prototype]]
的{{1}}(未显示)是“Object.prototype”。你在评论中说过:
我只是无法理解为什么在继承声明之后我们可以
的实例Human.prototype
返回Human.prototype
而不是[[Prototype]]
(它返回Male.prototype.isPrototypeOf(albert)
),因为true
是Human.isPrototypeOf(albert)
因为false
,函数在Male.prototype
的原型链中无处可去。让我们看看Human
的原型链:
Human
的{{1}}是albert
albert
的{{1}}是albert
[[Prototype]]
的{{1}}是Male.prototype
Male.prototype
的{{1}}是[[Prototype]]
如图:
+−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−+ | albert | | Male.prototype | | Human.prototype | | Object.prototype | +−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−+ | [[Prototype]] |−−−>| [[Prototype]] |−−−>| [[Prototype]] |−−−>| [[Prototype]]: null | +−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−+
因此Human.prototype
,该函数无处可去。