3

我有一个相当学术的问题,它并不特别适用于我正在做的任何事情,我真的很想知道答案!

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

TestObject = function(){};

它的原型中添加了一个方法,可以将其实例化为新对象本身:

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

最后:

使用原型方法实例化同名对象的含义是什么?为什么这会导致无限循环?(里面到底发生了什么……)

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

我只是不确定我是否在不知不觉中违反了任何最佳实践或约定。

4

1 回答 1

4

myObject.myProperty = new myObject.AnotherObject();

不同于

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

根本没有区别。请记住,JavaScript 中的对象有一个原型链。当您调用引擎时,new myObject.AnotherObject();将首先检查自身。如果找不到它,它将检查它会找到的原型。第二个版本AnotherObjectmyObjectmyObject

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

直接到AnotherObject定义的地方。


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

只需浏览代码。当你说: myObject.AnotherObject();,AnotherObject将被调用,this设置为myObject。第一行将尝试通过将myObjectthis设置为

new TestObject.prototype.AnotherObject(); 

然后它将重新进入相​​同的AnotherObject函数,但这次this设置为一个新对象,其原型设置为TestObject.prototype.AnotherObject的原型。以此类推,无止境


最后,

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 属性,它将在原型上的任何内容被检查之前找到并返回。

好吧,我的意思是,您总是可以说delete myObject.AnotherObject并从对象中删除该属性,然后您AnotherObject会发现原型上的存在,但实际上,您应该从一开始就避免这样的名称冲突。


关于你的最后一点代码

A) 为什么不制作User自己功能?B) 为什么不在ClientObject的构造函数中
设置正确?this.User = new ...()这样你就不需要undefined检查 C)ClientObject应该定义为

function ClientObject(){...` 

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

于 2013-06-03T02:21:53.000 回答