了解Prototype和这个

时间:2014-08-06 22:24:17

标签: javascript

据我所知,“this”应该包含实际用“this”触发函数的对象的属性和函数。 但在下面的例子中它还包含构造函数“foo”的属性,为什么?

function foo(id)
{
   var self = this;
   this.foo = "foo";
   this.element = document.getElementById(id);
   this.element.addEventListener("keyup", function(){self.bar();}, false);
}

foo.prototype.bar = function()
{
   console.log(this.element.value);
};
new foo("anyInputElement");

2 个答案:

答案 0 :(得分:2)

在JavaScript中,它是关于你是实例化还是仅仅调用一个函数。它只是前者的构造函数。正如您可能已经知道的那样,区别在于是否在函数引用之前使用了new关键字。

这可以控制构造函数中的属性是 的属性。

所以在你的情况下,它们不是构造函数的属性(这是一种无用的思考方式);相反,它们是您实例的属性

调用函数在window范围内执行,因此,如果您只是调用函数,this.foo等将在window上设置属性。

但是,如果实例化该函数,它们将成为实例上的属性,因为实例是从实例化而不是调用的函数(构造函数)中隐式返回的。所以:

调用:属性在默认上下文window上设置:

function static_func() { this.foo = 'bar'; }
static_func();
window.foo; //'bar'

实例化:属性在返回的实例

上设置
function constructor(val) { this.foo = val; }
var instance = new constructor('bar');
window.foo; //undefined
instance.foo; //'bar'

答案 1 :(得分:0)

所以你很困惑为什么当你把它保存在一个变量中时,以后它不是“这个”?有几个原因可以解释为什么self在后来的keyup事件中并不是“这个”。

当作为<input id="anyInputElement" />的结果调用keyup事件时,keyup事件的回调函数this将成为该输入。这是因为已创建新的执行上下文,导致this被分配给元素。

那么为什么不是self,而不是输入元素?

执行上下文是基于堆栈的。因此,当父函数foo用new实例化时,它会创建自己的执行上下文。这是keyup回调中使用的执行上下文的父上下文,因为它在堆栈中较低。每个执行上下文还包含词法和变量环境。这些环境包含可用的变量(命名冲突导致变量覆盖词法)。

this

词汇环境包含来自父环境的所有变量,一直到堆栈(这就是为什么function foo(id) { var self = this; //parent context this.element.addEventListener("keyup", function(){ self.bar(); //child context }, false); } 可以从任何地方访问的原因)。因此,这里的子执行上下文(在keyup回调中)在其词法环境中包含window

self包含来自父执行上下文的self副本

因此,当使用this时,即访问的执行上下文(包括词法和变量环境)。这是来自self的属性的来源。请注意,因为keyup回调创建了自己的执行上下文,所以它还有一个新创建的foo(这意味着self!=这在keyup事件监听器中)。

相关:Save access to this scope