关于关键字的javascript问题

时间:2012-03-15 13:52:19

标签: javascript firebug this

示例代码:

<!DOCTYPE html>
<html>
<head>
    <title>test</title>

    <script language="javascript" type="text/javascript">

    function init() {
        var nodeList = document.getElementsByTagName("a");
        var nodeArr = [];
        for( var i = 0; i < nodeList.length; i++) // Copy NodeList to Array
            nodeArr.push(nodeList[i]);
        for( var i = 0; i < nodeArr.length; i++) // Loop over array
            if( nodeArr[i].className == "clickLink" )
                nodeArr[i].onclick = clickLink2;    // Attach event function
    }

    window.onload = init; //Attach event function

    function clickLink2() { 
        console.log("this: " + this); //Prints window URL in href
        console.dir( this ); //show attributes of anchor    
        console.log( this.name ); // Prints name attribute
    }


    function clickLink( elem ) {
        console.log( "this: " + this ); //Prints [object Window]
        console.dir( this ); // Shows attributes, etc. al of [object Window]
        console.log( "name: " + elem.name );    
    }
    </script>

    </head>

    <body>

    <!-- inline -->
    <a href="#" name="blah1" onclick="clickLink(this); return false;">Test 1</a>
    <a href="#" name="blah2" onclick="clickLink(this); return false;">Test 2</a>
    <a href="#" name="blah3" onclick="clickLink(this); return false;">Test 3</a>
    <a href="#" name="blah4" onclick="clickLink(this); return false;">Test 4</a>


    <hr/>
    <!-- not inline -->
    <a href="#" name="blah5" class="clickLink">Test 5</a>
    <a href="#?t" name="blah6" class="clickLink">Test 6</a>
    <a href="#" name="blah7" class="clickLink">Test 7</a>
    <a href="#" name="blah8" class="clickLink">Test 8</a>

    </body>

    </html>

我在firefox中进行了测试,用firebug查看控制台输出。

现在我想知道:

  1. 为什么在clickLink 这个引用窗口对象?
  2. 为什么<{1}}中这个打印到控制台作为链接href的值?
  3. 有没有更好的方法将这个传递给这样一个不显眼的附件?你怎么能确定这个指的是什么?
  4. 好的,所以我从这里的答案中得到了一些内容,发现这个在某些浏览器中有点古怪。另外,为clickLink2分配函数与附加不同(但遗憾的是并非所有IE版本都支持onclick vs addEventListener)。由于某些原因,旧的IE也会在事件触发器函数体内使 this 仍然引用窗口对象而不是调用者。所以我使用了attachEvent。这是一些新的示例代码:

    event.srcElement

4 个答案:

答案 0 :(得分:2)

调用内联事件处理程序时,它们将在全局范围内运行。这就是为什么thiswindow

当事件处理程序实际附加到元素时,它们在该元素的上下文中被调用,就像运行作为对象一部分的方法一样。这使this成为元素。

例如:

function test(){
    console.log(this);
}
test();  // window

var obj = {
    test: test
}
obj.test(); // obj

要确定this是什么,您应该使用JS(包含element.addEventListenerelement.onClick)附加事件处理程序,而不是使用内联处理程序。

答案 1 :(得分:2)

这是我从.NET背景中学到的关于JavaScript的最神奇的事情之一。

this在方法中使用时,不引用特定对象。它引用调用者或引发事件的对象,该事件导致对事件处理程序的调用。

回答问题的第3个问题:只需将其引用的内容复制到新变量中:

var thisThis = this;
//now pass thisThis. Interesting huh? 
//thisThis will not change with the change of the context. 
//this alone is a keyword that changes depending on
//the context: e.g. who is the caller, what object raised the object, etc. 

答案 2 :(得分:2)

this是指向当前范围的变量。如果在控制台中执行以下代码:

var myPackage = {}
myPackage.method = function() {console.log(this)}
myPackage.method()

this将指向myPackage对象(method的范围)。

相反,如果您尝试运行以下内容:

console.log(this) // window

this(window)是对脚本执行的当前浏览器窗口的引用。

答案 3 :(得分:2)

1)为什么clickLink会引用窗口对象? 简单地说:clickLink不是事件处理程序,通过向元素添加属性onclick,您使用本机onclick方法作为调用函数的处理程序。此函数在主范围内声明,因此这指向窗口对象。 要明确:行为与此类似:

<p onclick='function(){window.clickLink(this);}'>

使实际的事件处理程序成为匿名函数,而不是clickLink。这就是为什么这将指向窗口:匿名函数也在全局范围内声明,因此clickLink的调用者是窗口。

2)为什么clickLink2中的这个打印到控制台作为链接的href值?

想想这句话'Javascript允许你操纵DOM,DOM树,所有事件和行为。'在init函数中,操作元素onclick行为。 onclick的默认方法被否决,并由此处的clickLink2方法取代nodeArr[i].onclick = clickLink2;

这样看:你的所有元素都有一个原型onclick方法,它接受一个参数。在第一种情况下,此参数是一个字符串,其值为clickLink函数的调用。然而,第二种情况是,具有特定类的实例具有其自己的onclick方法,从而推翻了原型的onclick。

我希望这能为你解决一些问题。一旦你掌握了事件,处理程序,方法,原型等背后的基本理念,并且克服了JS的怪癖,这很容易。

3)有没有更好的方法将此传递给这样一个不显眼的附件?你怎么能确定这是指什么?

嗯,有点回答上面那个,不是吗?但无论如何:如果你自己定义一个元素或对象的方法,一般来说,这将指向所有者对象/元素。如果您依赖于HTML和默认行为,JS将主要关注它自己的业务,这将指向窗口。

我不知道这是否是一个选项,但也许你可以尝试这样的事情:

<a onclick='clickLink'>

这应该是-in理论 - 与你的init函数做同样的事情

修改 工作替代上述内容:

<p onclick='clickLink.call(this)'>

调用将p元素定义为clickLink的调用者,将此指向调用该函数的元素。