首页 > 语言 > JavaScript > 正文

元素的内联事件处理函数的特殊作用域在各浏览器中存在差异

2024-05-06 14:25:41
字体:
来源:转载
供稿:网友

标准参考

无。

问题描述

在一个元素的属性中绑定事件,实际上就创建了一个内联事件处理函数(如<h1 onclick="alert(this);"...>...</h1>),内联事件处理函数有其特殊的作用域链,并且各浏览器的实现细节也有差异。

造成的影响

如果在元素的内联事件处理函数中使用的变量或调用的方法不当,将导致脚本运行出错。

受影响的浏览器

所有浏览器

问题分析

1. 内联事件处理函数的作用域链

与其他函数不同,内联事件处理函数的作用域链从头部开始依次是:调用对象、该元素的 DOM 对象、该元素所属 FORM 的 DOM 对象(如果有)、document 对象、window 对象(全局对象)。

如以下代码:

<form action="." method="get">	<input type="button" value="compatMode" onclick="alert(compatMode);"></form>

相当于1:

<form action="." method="get">	<input type="button" value="compatMode"></form><script>document.getElementsByTagName("input")[0].onclick=function(){	with(document){		with(this2.form)3{			with(this2){				alert(compatMode);			}		}	}}</script>

以上两种写法的代码在所有浏览器中都将弹出 document.compatMode 的值。

将上述代码中的 'compatMode' 替换为 'method',则在各浏览器中都将弹出 'get',即 INPUT 元素所在表单对象的 method 属性值。

注:
1. 这段代码仅为说明问题而模拟各浏览器的行为,并非表示所有浏览器都是如此实现的。
2. 是使用 this 关键字还是直接使用这个 DOM 对象,在各浏览器中有差异,详情请看本文 2.1 中的内容。
3. 是否添加 FORM 对象到作用域链中,各浏览器在实现上也有差异,详情请看本文 2.2 中的内容。

2. 内联事件处理函数的作用域链在各浏览器中的差异

参考 WebKit 的源码:

void V8LazyEventListener::prepareListenerObject(ScriptExecutionContext* context){  if (hasExistingListenerObject())    return;  v8::HandleScope handleScope;  V8Proxy* proxy = V8Proxy::retrieve(context);  if (!proxy)    return;  // Use the outer scope to hold context.  v8::Local<v8::Context> v8Context = worldContext().adjustedContext(proxy);  // Bail out if we cannot get the context.  if (v8Context.IsEmpty())    return;  v8::Context::Scope scope(v8Context);  // FIXME: cache the wrapper function.  // Nodes other than the document object, when executing inline event handlers push document, form, and the target node on the scope chain.  // We do this by using 'with' statement.  // See chrome/fast/forms/form-action.html  //   chrome/fast/forms/selected-index-value.html  //   base/fast/overflow/onscroll-layer-self-destruct.html  //  // Don't use new lines so that lines in the modified handler  // have the same numbers as in the original code.  String code = "(function (evt) {" /      "with (this.ownerDocument ? this.ownerDocument : {}) {" /      "with (            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选