【发布时间】:2017-08-19 03:53:27
【问题描述】:
我(或者至少我认为我是)非常熟悉 JavaScript 中 Hoisting 的概念。
考虑以下陈述:
函数声明会连同它的主体一起被提升,而函数表达式不会; 只有 var 语句会被提升。
“函数声明和函数变量总是被 JavaScript 解释器移动(‘提升’)到它们的 JavaScript 作用域的顶部” - Berry Cherry
现在考虑以下函数:
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
我是否应该使用原型向用户对象添加一个属性,但在原型声明之前在代码中访问它,它将工作(它被提升):
console.log("Hey there " + Dan.name + "! You have " + Dan.mana + " remaining mana.");
User.prototype.mana = 100;
这基本上向我证实了适用于函数和变量的相同提升原则也适用于原型。
问题 1:这个逻辑有效吗?如果有效,您能解释一下原因吗?
问题 2:如果没有将原型表达式移到原型函数调用之上,是否有办法避免这种情况?
谢谢,祝你愉快!
代码 sn-p:
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.");
【问题讨论】:
-
你的代码工作得很好(做一个 sn-p 你会看到)。错误在其他地方。此外,“提升”仅适用于变量,不会以任何方式提升对象属性。
-
感谢@georg 的回复!事实上,我忘了提到我在原型实现之前调用了 uppercut 方法。我编辑了帖子。另外,当您说对象属性不会以任何方式提升时,您到底指的是什么?我添加了 mana sn-p(之前忘记了)来证明通过原型添加的对象属性确实被提升了,而函数表达式没有。
-
你能把你的例子转换成一个可运行的sn-p吗? (使用编辑器中的 sn-p 按钮)。你的问题很难理解。
-
console.log不是说“你还有未定义的剩余法力值吗?” -
@Thai 当然会说 undefined。但这证明对象属性确实被提升。之后您可以更改每个 User 实例的值。
标签: javascript variables prototype hoisting