示例代码:
<!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查看控制台输出。
现在我想知道:
clickLink
这个引用窗口对象?好的,所以我从这里的答案中得到了一些内容,发现这个在某些浏览器中有点古怪。另外,为clickLink2
分配函数与附加不同(但遗憾的是并非所有IE版本都支持onclick
vs addEventListener
)。由于某些原因,旧的IE也会在事件触发器函数体内使 this 仍然引用窗口对象而不是调用者。所以我使用了attachEvent
。这是一些新的示例代码:
event.srcElement
答案 0 :(得分:2)
调用内联事件处理程序时,它们将在全局范围内运行。这就是为什么this
是window
。
当事件处理程序实际附加到元素时,它们在该元素的上下文中被调用,就像运行作为对象一部分的方法一样。这使this
成为元素。
例如:
function test(){
console.log(this);
}
test(); // window
var obj = {
test: test
}
obj.test(); // obj
要确定this
是什么,您应该使用JS(包含element.addEventListener
或element.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的调用者,将此指向调用该函数的元素。