javascript原型

时间:2011-07-01 23:47:45

标签: javascript prototype-programming

我试图理解js原型属性:我的示例代码

function Container(param) {
    this.member = param;
}

var newc = new Container('abc');


Container.prototype.stamp = function (string) {
    return this.member + string;
}

document.write(newc.stamp('def'));

function Box() {
    this.color = "red";
    this.member = "why";
}

Container.prototype = new Box();
Box.prototype.test = "whatever";
var b = new Box();

document.write(newc.test);

这里最后一行是未定义的 - 即使Container的原型是Box而Box的原型有属性测试,为什么引用Box中的test的newc不起作用?任何人都可以解释一下'Prototype'在我的上下文中的作用。

...谢谢

3 个答案:

答案 0 :(得分:2)

您已在Container实例创建后将Box()原型设置为newc

按如下方式对语句重新排序:

function Container(param) {
    this.member = param;
}

function Box() {
    this.color = "red";
    this.member = "why";
}

Container.prototype = new Box();
Box.prototype.test = "whatever";
Container.prototype.stamp = function (string) {
    return this.member + string;
}

//Here the containers prototype setup is complete.
var newc = new Container('abc');

document.write(newc.stamp('def'));

document.write(newc.test);

答案 1 :(得分:2)

如果您想知道为什么它的行为方式,而不仅仅是“修复”代码。所以这就是发生了什么。

如您所见,如果您更改“Container”的原型,您实际上将更改已实例化的新对象和对象的属性。所以:

function Container(param) {
    this.member = param;
}

var newc = new Container('abc');

// setting a new property of the prototype, after newc instantiated.
Container.prototype.stamp = function (string) {
    return this.member + string;
}

// This already-instantiated object can access the stamp function
document.write(newc.stamp('123')); // output: abc123

所以上面没有问题,只要你在定义之前不调用新方法。现在是下一点。将其添加到上面:

// Our Box object
function Box() {
    this.color = "red";
    this.member = "why";
}

Container.prototype = new Box();
var newd = new Container('fgh');
document.write(newd.stamp('456')); // output: ERROR

错误!但这是有道理的,对吧?你完全消灭了“容器”原型,并将其替换为“Box”中没有“邮票”功能的原型。

我假设您希望“Box”继承自“Container”。从命名约定来看,这是合乎逻辑的。如果您想这样做,请将上一部分替换为:

// Our Box object
function Box() {
    this.color = "red";
    this.member = "why";
}

// This inherits from Container. Note that we can
//   do this before or after we declare "Box"
Box.prototype = new Container();

Box.prototype.test = "Whatever";
var b = new Box("jkl"); // note: "jkl" is ignored because "Box" sets "member" to "why"

document.write(b.test); // output: Whatever
document.write("<br>");
document.write(b.stamp("345")); // output: why345

所以现在我们有一个“Box”可以调用自己的方法和参数,也可以从它的父“Container”调用它们。

所以大局观是一个对象会查看它自己的方法或类似的原型,如果它没有找到它,它会查看它继承的东西的原型,依此类推。另一个重点是在原型中设置某些东西使它在该对象的所有未来和当前实例中立即可用。

答案 2 :(得分:0)

对象不包含对其用于获取原型的构造函数的引用。如果确实如此,则代码将按预期工作。

相反,对象包含对其原型的引用,该原型在创建时设置。

来自语言规范部分4.2.1

  

构造函数创建的每个对象都有一个隐式引用(称为对象的原型)到其构造函数的“prototype”属性的值。此外,原型可能具有对其原型的非零隐式引用,依此类推;这被称为原型链。当引用对象中的属性时,该引用是原型链中包含该名称属性的第一个对象中该名称的属性。换句话说,首先检查直接提到的对象的这种属性;如果该对象包含命名属性,那么该引用引用的属性;如果该对象不包含命名属性,则接下来检查该对象的原型;等等。