我有一个相当学术性的问题,不适用于我正在做的任何事情,我只是想知道答案!

假设我们在全局 namespace 中有一个简单的对象定义,如下所示:

TestObject = function(){};

它在原型(prototype)中添加了一个方法,可以实例化为新对象本身:
TestObject.prototype.AnotherObject = function() {};

实例化第一个对象:
var myObject = new TestObject();

现在我的问题是这样的:

如何
myObject.myProperty = new myObject.AnotherObject();

不同于
myObject.myProperty = new TestObject.prototype.AnotherObject();

还是完全一样?

我看到的区别是:我可以使用第二种方法在TestObject上下文中实例化对象,而无需知道实例化对象本身的名称,即
TestObject.prototype.createAnObject = function() {
    this.anotherProperty = new TestObject.prototype.AnotherObject();
}

最后:

使用原型(prototype)方法实例化同名对象的含义是什么?为什么这会导致无限循环? (内部实际发生了什么。)
TestObject.prototype.AnotherObject = function () {
    this.AnotherObject = new TestObject.prototype.AnotherObject();
};
myObject.AnotherObject();

但这不是...
TestObject.AnotherObject = function() {};

TestObject.prototype.createAnObject = function() {
    this.AnotherObject = new TestObject.prototype.AnotherObject();
};
myObject.createAnObject();

...

我渴望了解这里的物体之间的关系!谢谢!

我问这些问题的原因是,我想做出这样的事情,使得对象之间存在1:1的关系:
ClientObject = function () {
    this.objectname = "a client class";
}

ClientObject.prototype.loginUser = function(name) {
    this.loggedin = true;
    if (typeof this.User === 'undefined') {
        this.User = new ClientObject.User(name);
    }
}
ClientObject.User = function (name) {
    this.username = name;
}

ClientObject.User.prototype.getProfile = function() {
    return 'user profile';
}

var testClient = new ClientObject();

console.log('testClient.User = ' + (typeof testClient.User)); // should not exist
testClient.loginUser('Bob'); // should login 'bob'
console.log('testClient.User = ' + (typeof testClient.User)); // should exist now Bob is logged in
console.log(testClient.User.username); // should be bob
testClient.loginUser('Tom'); // should not do anything as User object already created
console.log(testClient.User.username); // bob still
console.log(testClient.User.getProfile()); // new functionality available

我只是不确定我是否在不经意间破坏了任何最佳实践或惯例。

最佳答案



完全没有区别。请记住,JavaScript中的对象具有原型(prototype)链。当您调用new myObject.AnotherObject();时,引擎将首先在AnotherObject本身上检查myObject。找不到它,它将检查myObject的原型(prototype),它将找到。第二版

myObject.myProperty = new TestObject.prototype.AnotherObject();

只需转到定义AnotherObject的位置即可。
TestObject.prototype.AnotherObject = function () {
    this.AnotherObject = new TestObject.prototype.AnotherObject();
}
myObject.AnotherObject();

只需遍历代码。当您说:myObject.AnotherObject();时,将调用AnotherObject,并且this设置为myObject。第一行将尝试通过将其设置为的结果,在myObject(即this)上创建一个新属性。
new TestObject.prototype.AnotherObject();

然后将重新输入非常相同的AnotherObject函数,但是这次将this设置为一个新对象,该对象的原型(prototype)设置为TestObject.prototype.AnotherObject的原型(prototype)。等等广告无限

最后,
TestObject.prototype.createAnObject = function() {
    this.AnotherObject = new TestObject.prototype.AnotherObject();
}
myObject.createAnObject();

据我所知,并且据我测试,不是是否会导致无限循环:FIDDLE

基本上,createAnObject将以this设置为myObject进入。在其中将在myObject上创建一个名为AnotherObject的全新属性,该属性将设置为您先前设置的AnotherObject 函数的新调用。

请注意,进行此调用后,AnotherObject 函数仍将存在,,将由刚创建的AnotherObject属性由遮盖住。所以现在你永远无法说
var f = new myObject.AnotherObject()

因为您现在在myObject上有一个AnotherObject 属性属性,它将在对原型(prototype)进行任何检查之前找到并返回。

好吧,我的意思是,您总是可以说delete myObject.AnotherObject并从对象中删除该属性,这将使您可以在原型(prototype)中找到AnotherObject,但实际上,您应该避免这样的名称冲突。

关于最后的代码

A)为什么不让User成为自己的函数?
B)为什么不直接在ClientObject构造函数中设置this.User = new ...()?这样,您就不需要undefined检查
C)ClientObject应该定义为
function ClientObject(){...`

您现在拥有的似乎正在创建一个隐式全局。

10-06 00:31