我(或者至少我以为我)非常熟悉JavaScript中Hoisting的概念。
考虑以下陈述:
函数声明将与其正文一起提升,而函数表达式则不会; 只会提升var语句。
“函数声明和函数变量总是被JavaScript解释器” - Berry Cherry
移动('悬挂')到JavaScript范围的顶部
现在考虑以下功能:
function User() {
this.name = "";
this.life = 100;
this.heal = function heal(player) {
player.life+=5;
console.log("\nHey" + player.name + "! Player " + this.name + " healed you for 5.");
}
}
...以及以下用户:
var Dan = new User("Danny");
var Liz = new User("Lizzy");
假设我想以原型函数的形式向已定义的用户添加新的 技能 ,如此(附加到代码中):
User.prototype.uppercut = function uppercut(player) {
player.life-=10;
console.log("\nBaaam! " + player.name + ", player " + this.name + " uppercuted you for 10 damage.");
};
...现在,使用 技能 (在原型之前添加此功能) :
Liz.uppercut(Dan);
Liz.uppercut(Dan);
...我会收到以下错误:
Liz.uppercut(Dan);
^
TypeError: Liz.uppercut is not a function
我应该使用原型向User对象添加属性,但是在原型声明之前在代码中访问它,它将 工作 (它被提升):
console.log("Hey there " + Dan.name + "! You have " + Dan.mana + " remaining mana.");
User.prototype.mana = 100;
基本上,我向我确认同样的 提升 原则适用于功能&变量,也适用于原型。
问题1:这个逻辑是否有效,若然,你能解释一下原因吗?
问题2:如果有一种方法可以避免在原型函数调用之上移动原型表达式吗?
谢谢并且有一个好的!
代码段
function User(name) {
this.name = name;
this.life = 100;
this.heal = function heal(player) {
player.life+=5;
console.log("Hey" + player.name + "! Player " + this.name + " healed you for 5.");
}
}
var Dan = new User("Danny");
var Liz = new User("Lizzy");
Liz.uppercut(Dan);
Liz.uppercut(Dan);
console.log(Liz.name + " you know have " + Liz.life + " life.");
User.prototype.mana = 100;
User.prototype.uppercut = function (player) {
player.life-=10;
console.log("Baaam " + player.name + "! Player " + this.name + " uppercuted you for 10 damage.");
};
console.log("Hey there " + Dan.name + "! You have " + Dan.mana + " remaining mana.");
Dan.mana = 200;
console.log("Hey there " + Dan.name + "! You have " + Dan.mana + " remaining mana.");

答案 0 :(得分:0)
不,分配(原型属性或其他)不会被吊起。
代码
function User() { this.name = ""; … } var Dan = new User("Danny"); console.log("Hey there " + Dan.name + "! You have " + Dan.mana + " remaining mana."); User.prototype.mana = 100;
不起作用,它会记录Hey there ! You have undefined remaining mana.
。
答案 1 :(得分:0)
您在此处混淆变量和属性。变量被悬挂,属性没有。
在您的示例中,Dan
是变量,mana
是Dan
的属性。
JavaScript处理undefined
变量的方式与undefined
属性不同。
变量在声明时被悬挂。即var Dan = new User("Danny");
分为两个语句var Dan; Dan = new User("Danny");
。 var Dan
然后悬挂到函数的顶部。但任务仍然存在。
如果您的代码仅包含Dan = new User("Danny");
,则会收到ReferenceError,因为您将尝试对未声明的变量进行赋值。声明丢失了,因此该变量从未被提升过。
属性的运作方式不同。属性访问器返回父对象上的哈希查找结果。在Dan.mana
的情况下,定义了父对象,因此没有ReferenceError,但mana
不是Dan
的属性,因此散列查找返回undefined
。没有发生提升,因为没有变量声明。
因此,原型不能与吊装相关联,因为它们是严格的分配操作。即使原型在功能开始时被修改,它也不会受到提升的影响,因为提升仅 会影响变量的声明,而不是分配(发生在呼叫的右侧)。
答案 2 :(得分:0)
访问未在对象上定义的属性将为您提供undefined
。这里没有提升规则。
Liz.mana
将为您提供undefined
。Liz.uppercut
也会为您提供undefined
。Liz.agility
也会为您提供undefined
。调用Liz.uppercut(Dan)
会引发错误,因为您尝试将Liz.uppercut
作为函数调用undefined
。这导致“未定义不是函数”错误。