我目前正在研究javascript的基础知识,并且我很难理解这个图表(如下所示)。当调用FirmAnswer.get()时,为什么值为42 !!?不应该是未定义的!因为如果我没有弄错中的这个 函数中的<。> 函数fn2()指的是firmAnswer。
信用图表所有者
答案 0 :(得分:3)
这是一个麻烦的话题,我会给你的。
this
引用firmAnswer
是正确的,但即使firmAnswer
没有明确分配val
属性,val
也不是undefined
。为什么?因为val
原型链中的firmAnswer
位于更高位置,正如调用Object.create
所确定的那样,并且如您提供的图表所示。
评估this.val
时,这是幕后的事件序列:
val
属性直接附加到this
?不。查看this
的原型(对象answer
)。val
属性直接附加到answer
?是。使用它。答案 1 :(得分:3)
因为如果我没有弄错,那么在函数fn2()中返回this.val指的是firmAnswer
是的,确实如此,但是当您尝试从对象检索属性(val
)时,如果对象本身没有该属性,则JavaScript引擎会查找对象的原型。 firmAnswer
的原型是answer
(因为这是Object.create
用来设置的), 有val
,所以使用属性的值。这称为原型链,是原型继承的关键。
这是一个稍微简单的例子:
// Create an object with a `val`
var p = {
val: "p's value"
};
// Create an object using `p` as its prototype
var o = Object.create(p);
// Use `val` from `o` -- since `o` doesn't have `val`, the engine
// looks to `p`
snippet.log(o.val); // "p's value"
// Give `o` its own `val`
o.val = "o's value";
// Use it
snippet.log(o.val); // "o's value"
// Since this is based on whether `o` has `val` at all
// (not the *value* of `val`), we can *remove* `val`
// from `o` and start using `p`'s again:
// Remove `val` from `o` entirely
delete o.val;
// Use `val` again -- and we're back to using `p`'s
snippet.log(o.val); // "p' s value ""
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
答案 2 :(得分:2)
var firmAnswer = Object.create(answer);
以上陈述意味着'firmAnswer&#39;继承了所有的回答&#39; pro&amp;方法,answer.get()方法由firmAnswer.get()覆盖,但val属性不是。
答案 3 :(得分:2)
以下是它的运行方式:
firmAnswer.get()
; fn2
,this
设置为firmAnswer
; this.val
,this
设置为firmAnswer
; firmAnswer
是否定义了属性val
?不,让我们看看firmAnswer
的原型; firmAnswer
的原型已使用Object.create(answer)
指定,因此它是answer
; answer
是否定义了属性val
?是的,它是42
; 3
中,this.val
为42
; 2
返回42!!
。答案 4 :(得分:2)
'this'是firmAnswer,但它仍然继承自答案,因为使用Object.create设置了带答案的继承。所以它本身就找.val,找不到它,然后回答并从那里拿起它。
有关Object.create的信息,请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create。