我正在浏览一些JavaScript koans来学习语言语法,我对这组测试感到困惑:
it("should know that variables inside a constructor and constructor args are private", function () {
function Person(firstname, lastname)
{
var fullName = firstname + " " + lastname;
this.getFirstName = function () { return firstname; };
this.getLastName = function () { return lastname; };
this.getFullName = function () { return fullName; };
}
var aPerson = new Person ("John", "Smith");
aPerson.firstname = "Penny";
aPerson.lastname = "Andrews";
aPerson.fullName = "Penny Andrews";
expect(aPerson.getFirstName()).toBe("John");
expect(aPerson.getLastName()).toBe("Smith");
expect(aPerson.getFullName()).toBe("John Smith");
aPerson.getFullName = function () {
return aPerson.lastname + ", " + aPerson.firstname;
};
expect(aPerson.getFullName()).toBe("Andrews, Penny");
});
我得到构造函数中的变量是私有的,这就是为什么“John Smith”在调用getFullName()时仍会打印,即使在尝试设置aPerson.firstname,lastname和fullName之后也是如此。但是后来创建了一个名为getFullName()的函数,然后调用函数“Andrews,Penny”打印。
我本来期望“史密斯,约翰”打印,因为这个新功能是在“失败”尝试将名字设置为“Penny”并将姓氏设置为“安德鲁斯”之后创建的。为什么“安德鲁斯,便士”打印?
由于
答案 0 :(得分:1)
这里的关键是 new
operator ; var aPerson = new Person ("John", "Smith")
创建一个新的Person
,传入John
和Smith
作为Person
函数使用的名称,并将新函数实例分配给变量aPerson
。
请注意var fullName = firstname + " " + lastname
函数内的Person
。这将调用Person
函数时作为函数参数传递的任何内容。此时,this.getFullName
将等于John Smith
。
当您运行aPerson.firstname = "Penny"
时
这只会更新Person
的新实例;它不会修改原始的Person
函数。当您致电aPerson.getFirstName()
时,getFirstName()
方法会返回 firstname
(约翰)最初设置为Person
的内容,而不是已为新实例aPerson
(Penny)。
因此,当您第一次拨打aPerson.getFullName()
时,名称为John Smith
。
您的新功能aPerson.getFullName = function () { }
会返回aPerson.lastname + ", " + aPerson.firstname
。与上一个函数不同,它使用Person
(Penny Andrews)的 new 实例中的姓氏和名字。
因此,第二次拨打aPerson.getFullName()
时,名称为Penny Andrews
。
希望这有帮助! :)
答案 1 :(得分:0)
首先,您需要了解这一点:
function Person(firstname, lastname)
{
var fullName = firstname + " " + lastname;
...
}
var aPerson = new Person ("John", "Smith");
在这里,你创建的唯一东西是一个只有方法的对象,甚至不是属性,比如firstname,lastname。 (用var声明的参数和变量没有附加到您的对象)
所以你的对象aPerson是这样的:
{
getFirstName: function(), // => John
getLastName: function(), // => Smith
getFullName: function() // => John Smith
}
然后:
aPerson.firstname = "Penny";
aPerson.lastname = "Andrews";
aPerson.fullName = "Penny Andrews";
您在aPerson对象上分配了新属性。所以,它变成了这样:
{
firstname: "Penny",
lastname: "Andrews",
fullName: "Penny Andrews",
getFirstName: function(), // => John
getLastName: function(), // => Smith
getFullName: function() // => John Smith
}
接下来,用这个覆盖getFullName:
aPerson.getFullName = function () {
return aPerson.lastname + ", " + aPerson.firstname;
};
如您所见,您使用这些新属性。
现在,您应该能够理解您的结果。 如果你做了替换,你会得到这个:
aPerson.getFullName = function () {
return aPerson.lastname + ", " + aPerson.firstname;
// Andrews , Penny
};
瞧!这就是你获得结果的原因;)