在查看Cookie Clicker源代码时,我注意到了一个奇特的Game对象系统,他使用了新的Game.Building(" cursor" ...)。然后我决定用自己的代码测试这个,所以我用基本的用户变量做了同样的事情。
AI.User = function(username, password) {
try {
this.username = username;
this.password = password;
this.setUsername = function(username) { this.username = username; };
this.setPassword = function(password) { this.password = password; };
this.getUsername = function() { return this.name; };
this.getPassword = function() { return this.password; };
this.GetUserByUsername = function(username) { };
return true;
}
catch(err) {
console.log(err);
return false;
}
};
new AI.User("John Smith", "JSmith42");
问题是我不知道如何访问创建的变量。
答案 0 :(得分:0)
如果你问为什么要创建这样的变量,那是因为它是该变量的构造函数。您可以只调用构造函数并使用传入的值填充正确的参数,而不是创建没有名称或密码的User对象并在以后设置它。
答案 1 :(得分:0)
这是在javascript中使用OO样式的简单方法。
如果您想了解更多内容,可以参考this post。
答案 2 :(得分:0)
您需要在变量中捕获new
表达式的结果:
var user = new AI.User("John Smith", "JSmith42");
console.log(user.getUsername();); // outputs "John Smith"
请注意,您还可以使用函数的.prototype
属性创建一次getter和setter,而不必在每次有人创建新对象时重新创建它们。以下是an article I wrote:
function Person(first, last)
{
this.first = first;
this.last = last;
}
var john = new Person("John", "Doe");
var mary = new Person("Mary", "Deer");
Person.prototype.full = function() {return this.first + " " + this.last;};
alert(john.full()); // "John Doe"
这里发生了很多事情。
- 我们创建了一个
function
,在调用时会在其this
对象上设置属性。- 我们通过在函数调用之前放置
new
关键字来创建该函数的两个单独实例。这可确保john
和mary
引用完全独立的对象,每个对象都有自己的first
和last
属性。- 我们创建了一个新功能,并将其分配到
full
功能Person
媒体资源的prototype
媒体资源中。prototype
属性存在于所有函数上,并允许您定义应该存在于从该函数创建的每个对象上的后备属性。- 我们在
醇>full()
上调用john
函数。 JavaScript看到john
对象实际上没有full
函数,因此它会查找Person.prototype.full()
函数并调用它。但是,在该调用中,this
仍然引用john
对象。
答案 3 :(得分:0)
当你使用new
运算符的函数(即作为构造函数)时,它实际上将函数包装在一个额外的代码中以创建一个新对象,它设置为this
,并且然后在最后返回该对象。 **因此,要保存调用结果,只需将其分配给变量,例如var myUser = new AI.User("John Smith", "JSmith42");
进入细节,你可以想到它有点像这样。 我要提供的代码与幕后实际发生的代码不完全匹配,但它涵盖了基础知识:
function constructObject(constructor) {
var newPrototype = constructor.prototype || Object.prototype,
newThis = Object.create(newPrototype),
constructorResult;
constructor.apply(
newThis,
Array.prototype.slice.call(arguments, 1)
);
if (constructorResult !== undefined) {
return constructorResult;
}
return newThis;
}
当你调用“new Constructor(a,b,c)”时,它就像我在这里提到的那样调用“constructObject(constructor,a,b,c)”。
第2行中的“Object.create”创建了一个全新的对象,其原型与我们传入的内容相同。请注意,newPrototype从constructor.prototype
中获取,如果不存在则,Object.prototype
。然后,这个“newPrototype”对象成为我们传递的对象的原型。
“constructor.apply”然后调用构造函数,将newThis
对象设置为this
进行该调用,并传入我们可能拥有的任何其他参数但将构造函数移出。我们保存函数的返回值,即使构造函数返回任何内容都是不好的做法。
这是一个问题:如果由于某种原因构造函数返回了一个对象,那么我们将返回该对象而不是我们创建的对象。否则,我们会返回新对象。这是我的代码与实际情况不完全匹配的重点之一,因为引擎有更好的方法来检查返回的内容。
使用new
而不将结果保存在变量中并不是一种好习惯。它有效,但看起来很奇怪,我怀疑这是你看到它时感到困惑的部分原因。
Cookie Clicker基本上在JavaScript的之上实现了自己的简单“类OO”系统。有三种对象:Game.Object,Game.Upgrade和Game.Achievement。没有继承,原型或其他,但因为它通过一系列回调函数工作,所以仍然存在一种多态性。
new
运算符与标准JavaScript 中的运算方式相同。关键是所有三个基本构造函数在每次调用时都会保存对this
的引用,在Game对象中的三个列表之一中。 这就是Cookie Clicker如何密切关注它创建的对象而不将它们保存在变量中:它实际上是这样,而不是“在开放式”。最终的结果几乎就像一种表格(除了其他东西,因为游戏对象很大)。
模仿这种风格可能不是一个好主意。它看起来没有其他JavaScript代码,这可能是它为什么如此混淆你的很大一部分原因。 Orteil本人似乎正在远离它:Idle Game Maker(他的后续引擎)的源代码与Cookie Clicker非常相似,但对象系统已经消失。这是一个黑魔法:这是一个有趣的研究JavaScript的深奥细节,但不是你应该实际练习的东西。
考虑到Cookie Clicker的主题,这是完全合适的。