我一直在使用javascript,但从未学过语言超过基础知识.我正在阅读John Resig的"Pro Javascript技术" - 我想出了一些问题,但我没有在书中或谷歌上找到答案.
约翰在他的书中给出了这个例子:
功能#1
function User( name, age ){
this.name = name;
this.age = age;
}
// Add a new function to the object prototype
User.prototype.getName = function(){
return this.name;
};
User.prototype.getAge = function(){
return this.age;
};
var user = new User( "Bob", 44 );
console.log("User: " + user.getName() + ", Age: " + user.getAge());
Run Code Online (Sandbox Code Playgroud)
我还在学习原型属性,所以我尝试写类似的东西:
功能#2
function User (name, age ) {
this.name = name;
this.age = age;
this.getName = function() {
return this.name;
};
this.getAge = function() {
return this.age;
};
}
var user = new User( "Bob", 44 );
console.log("User: " + user.getName() + ", Age: " + user.getAge());
Run Code Online (Sandbox Code Playgroud)
它不使用prototype属性来创建getName和getAge函数,但输出与John的示例相同.
我更进了一步,创造了这个:
功能#3
var User = {
name: "",
age: 0,
setName: function(name) {
this.name = name;
},
setAge: function(age) {
this.age = age;
},
getName: function() {
return this.name;
},
getAge: function() {
return this.age;
}
};
User.setName("Bob");
User.setAge(44);
console.log("User: " + User.getName() + ", Age: " + User.getAge());
Run Code Online (Sandbox Code Playgroud)
再次 - 它看起来与John的例子不同(我必须添加setter方法),但输出是相同的.
问题#1 - 3个功能有什么区别?prototype属性的优点是什么,而且Function#2做错了什么,因为它似乎更直接代码#2而不是#1(尽管我确信#1在John创建它时更好看) .
问题#2 - 如何修改函数#3以不使用setName和setAge方法,但仍保留{...}简写?{...}速记可以有构造函数吗?
在此先感谢帮助我学习!
编辑 我认为我的第二个问题有点令人困惑.我的意思是我怎么能用{...}简写来创建一个User对象,但是在我创建了这个对象之后,请说:
var user = new User("Bob", 44);
Run Code Online (Sandbox Code Playgroud)
就像在功能#1中一样 - 或者那是不可能的?
编辑#2 哇!谢谢大家的精彩回答.这真的让我更加清楚.因此,如果我理解正确,#1和#2之间的差异不会太大.如果我只创建一个"用户"对象 - 它们可能完全不同.但是如果我的程序创建了许多用户对象,那么#1很可能会更有效并且使用更少的内存,因为所有对象将共享相同的功能.
我非常感谢所有伟大的答案 - 谢谢!
And*_*isi 22
每次计算function(){}时,它都会创建一个新的函数对象.因此,在#1中,所有User对象共享相同的getName和getAge函数,但在#2和#3中,每个对象都有自己的getName和getAge副本.所有不同的getName函数都表现完全相同,因此您无法看到输出中的任何差异.
{...}简写是一个构造函数.在计算时,它构造一个具有给定属性的新"对象".当您运行"新用户(...)"时,它会构造一个新的"用户".您碰巧创建了一个与用户具有相同行为的Object,但它们的类型不同.
回复评论:
你不能,直接.您可以创建一个按#3创建新对象的函数.例如:
function make_user(name, age) {
return {
name: name,
age: age,
getName: function() { return name; },
getAge: function() { return age; },
};
}
var user = make_user("Joe", "18");
Run Code Online (Sandbox Code Playgroud)
Ber*_*iri 12
如果你想在JavaScript中做OOP,我强烈建议你查看闭包.我开始用这三个网页学习这个主题:
http://www.dustindiaz.com/javascript-private-public-privileged/
http://www.dustindiaz.com/namespace-your-javascript/
http://blog.morrisjohns.com/javascript_closures_for_dummies
1,2和3之间的差异如下:1)是向现有对象添加新方法的示例.2)与#1相同,但用户功能中的对象中包含某些方法.3)是使用JSON定义对象的示例.缺点是您不能使用new(至少不使用该示例)来定义该对象的新实例.但是,您确实可以获得方便的JSON编码风格.
如果你还不知道,你肯定应该阅读JSON.当您理解JSON时,JavaScript会更有意义.
编辑 如果要在函数#3中使用new,可以将其编写为
function User() {
return {
name: "",
age: 0,
setName: function(name) {
this.name = name;
},
setAge: function(age) {
this.age = age;
},
getName: function() {
return this.name;
},
getAge: function() {
return this.age;
}
};
}
Run Code Online (Sandbox Code Playgroud)
当然,所有这些功能和属性都将是公开的.要将它们设为私有,您需要使用闭包.例如,您可以使用此语法将年龄和名称设为私有.
function User() {
var age=0;
var name="";
return {
setName: function(name_) {
name = name_;
},
setAge: function(age_) {
age = age_;
},
getName: function() {
return name;
},
getAge: function() {
return age;
}
};
}
Run Code Online (Sandbox Code Playgroud)
您可以访问姓名和年龄,而无需使用此类功能.在javascript中,你必须使用不同的黑客来保持私密或受保护的东西.
这个
User.name = "BoB";
User.age = 44;
Run Code Online (Sandbox Code Playgroud)
将产生与您的示例相同的输出.
没有构造函数,因为它们出现在其他语言中.最简单的方法是定义init()函数,并在实例化对象后立即调用它.
但我最重要的提示是研究http://www.prototypejs.org/.这是一个javascript库,有很多很酷的功能,试图让javascript"更多OO*".
使用原型库,您可以使类的行为更像真正的OOP类.它还具有构造函数.
编辑:至于你在评论中提到的内容:
person = new User();
person.name = "Bob";
person.age = 44;
Run Code Online (Sandbox Code Playgroud)