Javascript 原型

Javascript 原型,javascript,prototype-programming,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() {

我试图理解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);
这里最后一行是未定义的——即使容器的原型是一个盒子,盒子的原型有一个属性测试,为什么提到盒子中的测试的newc不起作用?请任何人解释一下“原型”在我上面的上下文中是如何工作的


谢谢…

在创建了
newc
实例之后,您正在将
Container
prototype设置为
Box()

将语句重新排序如下:

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);

对象不包含它用来获取原型的构造函数的引用。如果确实如此,那么代码将按照您的预期工作

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

从语言规范部分:

由构造函数创建的每个对象都对其构造函数的“prototype”属性的值有一个隐式引用(称为对象的prototype)。此外,原型可能具有对其原型的非空隐式引用,等等;这被称为原型链。当引用对象中的某个属性时,该引用是指原型链中包含该名称属性的第一个对象中该名称的属性。换言之,首先检查直接提及的对象是否具有此类属性;如果该对象包含命名属性,则该属性是引用所引用的属性;如果该对象不包含命名属性,那么接下来将检查该对象的原型;等等


如果听起来你想知道为什么它会这样,而不仅仅是“修复”代码。这就是发生的事情

如您所见,如果您更改“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”从“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对象
函数框(){
this.color=“red”;
this.member=“为什么”;
}
//这是从容器继承的。请注意,我们可以
//在我们声明“盒子”之前或之后执行此操作
Box.prototype=新容器();
Box.prototype.test=“无论如何”;
var b=新框(“jkl”);//注意:“jkl”被忽略,因为“Box”将“member”设置为“why”
记录。写(b.测试);//输出:不管怎样
文件。写(“
”); 文件。书写(b.印章(“345”);//输出:why345
现在我们有了一个“盒子”,它可以调用自己的方法和参数,也可以从其父“容器”调用它们


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

正如@Scrum-Meister所说,在创建实例后,您可以设置
容器的
原型。该实例仍将指向旧原型。您只需对问题的答案进行注释,不必“编辑”答案。@FelixKling我认为如果您的评分为1,您就不能进行注释:我认为在设置
Box.prototype.test=“whatever”之前,如果您定义该实例,示例会更好属性。这将更清楚地表明,唯一“有问题”的行是
Container.prototype=newbox()。上一段你把我弄丢了。。。在长方体示例中,长方体的原型现在是容器,对吗?从您的语句中可以看出,Box有一个原型,检查它,如果没有原型,则使用容器的原型。@justnS,Box最初将其原型设置为实例化的容器对象。这使得Box继承了容器。然后,我们直接在Box原型中设置进一步的参数。这将创建新参数或覆盖从容器继承的参数。清澈如泥?