中文字幕免费精品_亚洲视频自拍_亚洲综合国产激情另类一区_色综合咪咪久久

元素的內聯事件處理函數的特殊作用域在各瀏覽器中存在差異
來源:易賢網 閱讀:1164 次 日期:2015-04-22 10:36:08
溫馨提示:易賢網小編為您整理了“元素的內聯事件處理函數的特殊作用域在各瀏覽器中存在差異”,方便廣大網友查閱!

問題描述

在一個元素的屬性中綁定事件,實際上就創建了一個內聯事件處理函數(如<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 (this.form ? this.form : {}) {" \

"with (this) {" \

"return (function(evt){";

code.append(m_code);

// Insert '\n' otherwise //-style comments could break the handler.

code.append( "\n}).call(this, evt);}}}})");

v8::Handle<v8::String> codeExternalString = v8ExternalString(code);

v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, m_sourceURL, m_lineNumber);

if (!script.IsEmpty()) {

v8::Local<v8::Value> value = proxy->runScript(script, false);

if (!value.IsEmpty()) {

ASSERT(value->IsFunction());

v8::Local<v8::Function> wrappedFunction = v8::Local<v8::Function>::Cast(value);

// Change the toString function on the wrapper function to avoid it

// returning the source for the actual wrapper function. Instead it

// returns source for a clean wrapper function with the event

// argument wrapping the event source code. The reason for this is

// that some web sites use toString on event functions and eval the

// source returned (sometimes a RegExp is applied as well) for some

// other use. That fails miserably if the actual wrapper source is

// returned.

DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, toStringTemplate, ());

if (toStringTemplate.IsEmpty())

toStringTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8LazyEventListenerToString));

v8::Local<v8::Function> toStringFunction;

if (!toStringTemplate.IsEmpty())

toStringFunction = toStringTemplate->GetFunction();

if (!toStringFunction.IsEmpty()) {

String toStringResult = "function ";

toStringResult.append(m_functionName);

toStringResult.append("(");

toStringResult.append(m_isSVGEvent ? "evt" : "event");

toStringResult.append(") {\n ");

toStringResult.append(m_code);

toStringResult.append("\n}");

wrappedFunction->SetHiddenValue(V8HiddenPropertyName::toStringString(), v8ExternalString(toStringResult));

wrappedFunction->Set(v8::String::New("toString"), toStringFunction);

}

wrappedFunction->SetName(v8::String::New(fromWebCoreString(m_functionName), m_functionName.length()));

setListenerObject(wrappedFunction);

}

}

}

從以上代碼可以看出,WebKit 在向作用域鏈中添加對象時,使用了 'this' 關鍵字,并且通過判斷 'this.form' 是否存在來決定是否添加 FORM 對象到作用域鏈中。

其他瀏覽器中也有類似的實現方式,但在各瀏覽器中,將目標對象(即綁定了此內聯事件處理函數的對象)添加到作用域鏈中的方式有差異,判斷并決定是否在作用域鏈中添加 FORM 對象的方法也不相同。

2.1. 各瀏覽器在生成這個特殊的作用域鏈時添加目標對象時使用的方法不同

各瀏覽器都會將內聯事件處理函數所屬的元素的 DOM 對象加入到作用域鏈中,但加入的方式卻是不同的。

如以下代碼:

<input type="button" value="hello" onclick="alert(value);">

在所有瀏覽器中,都將彈出 'hello'。

再修改代碼以變更 INPUT 元素的內聯事件處理函數的執行上下文:

<input type="button" value="hello" onclick="alert(value);">

<script>

var $target=document.getElementsByTagName("input")[0];

var o={

onclick:$target.onclick,

value:"Hi, I'm here!"

};

o.onclick();

</script>

在各瀏覽器中運行的結果如下:

IE ChromeHi, I'm here!

Firefox Safari Operahello

可見,各瀏覽器將內聯事件處理函數所屬的元素的 DOM 對象加入到作用域鏈中的方式是不同的。

在 IE Chrome 中的添加方式類似以下代碼:

<input type="button" value="hello">

<script>

var $target=document.getElementsByTagName("input")[0];

$target.onclick=function(){

with(document){

with(this){

alert(value);

}

}

}

</script>

而在 Firefox Safari Opera 中的添加方式則類似以下代碼:

<input type="button" value="hello">

<script>

var $target=document.getElementsByTagName("input")[0];

$target.onclick=function(){

with(document){

with($target){

alert(value);

}

}

}

</script>

由于極少需要改變內聯事件處理函數的執行上下文,這個差異造成的影響并不多見。

2.2. 各瀏覽器在生成這個特殊的作用域鏈時對于在何種情況下添加 FORM 對象有不同理解

各瀏覽器都會將內聯事件處理函數所屬的 FORM 對象加入到作用域鏈中,但如何判斷該元素是否“屬于”一個表單對象,各瀏覽器的處理方式則不相同。

如以下代碼:

<form action="." method="get">

<div>

<span onclick="alert(method);">click</span>

</div>

</form>

<script>

document.method="document.method";

</script>

在各瀏覽器中,點擊 SPAN 元素后彈出的信息如下:

IE Safari Operaget

Chrome Firefoxdocument.method

可見:

IE Safari Opera 將 FORM 對象加入到了內聯事件處理函數的作用域鏈中,是否加入 FORM 對象看起來是由這個元素是否是一個 FORM 的子孫級元素來決定的。因此在這些瀏覽器中,函數內的變量 'method' 最終得到的是 FORM 的 'method' 的值。

Chrome Firefox 沒有將 FORM 對象加入到內聯事件處理函數的作用域鏈中,判斷是否加入 FORM 對象是看該函數綁定的目標對象的 'form' 屬性是否存在。從上文中的 WebKit 的源碼中可以看到 Chrome 正是使用了 'this.form' 來判斷,只有目標元素是一個 FORM 的子孫級元素并且該目標元素是一個表單元素時,'form' 屬性才會存在。本例中的 SPAN 元素并不是表單元素,因此變量 'method' 最終得到的是 'document.method' 的值。

如果將以上代碼中的 SPAN 元素更換為 INPUT 元素或其他表單元素,則在所有瀏覽器中的表現將一致。

3. 由于內聯事件處理函數的這種特殊的作用域鏈而產生問題的實例

3.1. 在元素的內聯事件處理函數中訪問的變量意外的與該該函數作用域鏈中非全局對象的其他對象的屬性重名時出現的問題

當一個內聯事件處理函數中訪問的變量意外的與該函數作用域鏈中非全局對象(window)的其他對象的屬性重名,將導致該變量的實際值不是預期值。

假設有以下代碼:

<button onclick="onsearch()"> click here </button>

<script>

function onsearch(){

alert("Click!");

}

</script>

作者本意為點擊按鈕即彈出“Click!”信息,但 WebKit 引擎瀏覽器的 HTMLElement 對象都有一個名為 onsearch 的事件監聽器,這將導致上述代碼在 Chrome Safari 中不能按照預期執行。本例中由于該監聽器未定義(為 null),因此將報 “Uncaught TypeError: object is not a function” 的錯誤。

附:在上述代碼中,追加以下代碼確認 'onsearch' 的位置:

<script>

var o=document.getElementsByTagName("button")[0];

if("onsearch" in o)alert("當前對象有 onsearch 屬性。");

if(o.hasOwnProperty("onsearch"))alert("onsearch 屬性是當前對象私有。");

</script>

3.2. 在表單內的子孫級非表單元素的內聯事件處理函數中試圖調用表單的屬性或方法時出現的問題

假設有以下代碼:

<form action="xxx" method="get">

...

<a href="#" onclick="submit();">click</a>

</form>

作者本意為點擊 A 元素后調用 FORM 的 'submit' 方法,但 Chrome Firefox 并未將 FORM 對象加入到該內聯事件處理函數的作用域鏈中,因此以上代碼在 Chrome Firefox 中并不能正常運行。

解決方案

1. 盡量不要使用內聯事件處理函數,使用 DOM 標準的事件注冊方式為該元素注冊事件處理函數,如:

<button> click here </button>

<script>

function onsearch(){

alert("Click!");

}

function bind($target,eventName,onEvent){

$target.addEventListener?$target.addEventListener(eventName,onEvent,false):$target.attachEvent("on"+eventName,onEvent);

}

bind(document.getElementsByTagName("button")[0],"click",onsearch);

</script>

2. 必須使用內聯事件處理函數時,要保證該函數內試圖訪問的變量是位于全局作用域內的,而不會因該函數獨特的作用域鏈而引用到非預期的對象。最簡單的辦法是使用前綴,如 'my_onsearch'。

更多信息請查看IT技術專欄

更多信息請查看腳本欄目
由于各方面情況的不斷調整與變化,易賢網提供的所有考試信息和咨詢回復僅供參考,敬請考生以權威部門公布的正式信息和咨詢為準!

2026上岸·考公考編培訓報班

  • 報班類型
  • 姓名
  • 手機號
  • 驗證碼
關于我們 | 聯系我們 | 人才招聘 | 網站聲明 | 網站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺 | 手機站點 | 投訴建議
工業和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網安備53010202001879號 人力資源服務許可證:(云)人服證字(2023)第0102001523號
云南網警備案專用圖標
聯系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關注公眾號:hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權所有:易賢網
云南網警報警專用圖標
中文字幕免费精品_亚洲视频自拍_亚洲综合国产激情另类一区_色综合咪咪久久
亚洲国产cao| 国产一区二区三区av电影| 欧美色区777第一页| 激情欧美丁香| 欧美精品久久99| 亚洲小说欧美另类社区| 国产亚洲精品7777| 蜜桃av久久久亚洲精品| 亚洲最新视频在线播放| 国产日韩精品久久| 欧美国产一区视频在线观看| 一区二区三区 在线观看视频| 国产精品久久久久久久久久直播 | 欧美成人午夜| 在线不卡视频| 国产精品videosex极品| 久久中文字幕一区| 亚洲视频图片小说| 亚洲第一网站| 国产精品网站在线| 欧美韩日一区二区| 久久成人18免费网站| 99热精品在线| 亚洲电影免费观看高清完整版在线观看| 欧美日韩国产黄| 免费国产一区二区| 久久www成人_看片免费不卡| 99精品欧美| 一区二区视频免费完整版观看| 国产精品porn| 欧美日韩国产色视频| 久久久精品999| 午夜精品网站| 亚洲午夜激情网页| 亚洲精品系列| 亚洲国产婷婷香蕉久久久久久99| 国产视频亚洲| 国产精品视频导航| 在线观看国产日韩| 国产精品女主播一区二区三区| 欧美电影免费观看| 久久久水蜜桃| 久久久久久久999精品视频| 午夜影视日本亚洲欧洲精品| 在线亚洲精品福利网址导航| 亚洲伦伦在线| 91久久国产综合久久蜜月精品| 极品尤物av久久免费看| 极品少妇一区二区三区精品视频 | 经典三级久久| 国产一区日韩二区欧美三区| 国产精品一卡| 国产欧美综合一区二区三区| 国产精品伊人日日| 国产视频亚洲| 国内伊人久久久久久网站视频| 国产一区二区激情| 激情综合网激情| **性色生活片久久毛片| 亚洲国产婷婷| 在线亚洲欧美专区二区| 99re8这里有精品热视频免费 | 欧美α欧美αv大片| 亚洲国产高清自拍| 亚洲人久久久| 精品av久久707| 91久久精品日日躁夜夜躁欧美 | 欧美在线观看网站| 久久精品视频在线免费观看| 狂野欧美性猛交xxxx巴西| 欧美成人在线免费观看| 欧美日韩亚洲一区二区三区在线| 欧美午夜无遮挡| 国产欧美日韩激情| 伊人久久大香线蕉av超碰演员| 亚洲欧洲一区二区天堂久久| 亚洲婷婷国产精品电影人久久| 亚洲男人天堂2024| 国产精品久久久久一区二区| 国产精品国产三级国产a| 国产有码一区二区| 91久久夜色精品国产九色| 亚洲桃花岛网站| 久久久久一区二区三区| 欧美日韩aaaaa| 国产深夜精品| 日韩午夜在线视频| 欧美中文字幕久久| 欧美日韩国产精品一区| 国产日产欧产精品推荐色| 亚洲国产婷婷香蕉久久久久久99| 亚洲少妇中出一区| 久久频这里精品99香蕉| 欧美天天在线| 亚洲国产精选| 欧美专区一区二区三区| 欧美日韩一区二区三区在线看| 国产亚洲精品综合一区91| 欧美午夜不卡在线观看免费 | 国产精品丝袜白浆摸在线| 1024日韩| 久久福利电影| 国产精品久久久久aaaa樱花| 亚洲欧洲一区二区天堂久久| 久久精品二区| 国产精品美女久久久浪潮软件 | 久久久免费精品视频| 欧美不卡在线视频| 国产偷久久久精品专区| 中文精品视频一区二区在线观看| 久久精品日韩欧美| 国产精品亚洲激情| 久久视频这里只有精品| 久久综合久久综合久久| 国产精品女同互慰在线看| 亚洲精品一二区| 欧美1区3d| 亚洲盗摄视频| 久久人人97超碰人人澡爱香蕉| 国产精品一区二区三区免费观看| 亚洲精品久久久久久久久久久久久| 久久经典综合| 国产一区视频网站| 国产精品久久久久久久久搜平片| 亚洲欧洲一区二区天堂久久| 美日韩精品视频| 亚洲二区在线视频| 麻豆精品传媒视频| 伊人久久成人| 免费成人黄色| 91久久精品国产91性色| 欧美精品成人| 中文欧美日韩| 国产精品专区第二| 欧美亚洲一区二区在线| 国产欧美日韩在线观看| 久久久久久久一区二区三区| 狠狠色综合网站久久久久久久| 欧美一级在线播放| 国内精品视频666| 免费观看成人鲁鲁鲁鲁鲁视频| 精品av久久久久电影| 麻豆精品在线播放| 亚洲精选在线观看| 国产精品久久久一区二区| 欧美一区日韩一区| 亚洲电影专区| 国产精品久久久| 久久精品在线| 亚洲人成网站色ww在线| 欧美午夜精品理论片a级按摩 | 激情六月综合| 蜜臀久久久99精品久久久久久| 在线欧美福利| 欧美视频在线一区二区三区| 午夜欧美精品久久久久久久| 激情自拍一区| 国产精品v欧美精品v日韩精品| 午夜欧美大尺度福利影院在线看| 国内外成人免费视频 | 欧美精品自拍| 亚洲一品av免费观看| 国产在线播放一区二区三区| 欧美成人影音| 欧美一级淫片播放口| 伊人精品久久久久7777| 欧美手机在线| 美女网站在线免费欧美精品| 亚洲午夜激情免费视频| 在线观看免费视频综合| 欧美日韩精品免费在线观看视频| 欧美一区二区女人| 亚洲精品免费网站| 国产一区自拍视频| 亚洲欧洲日韩女同| 国产免费成人在线视频| 老司机一区二区| 性色一区二区三区| 1024亚洲| 国产真实乱子伦精品视频| 牛牛国产精品| 欧美色视频在线| 老司机一区二区| 亚洲欧美制服另类日韩| 亚洲大胆在线| 国产一区二区丝袜高跟鞋图片| 欧美日韩在线精品一区二区三区| 久久久久久一区二区三区| 亚洲专区一区| 亚洲香蕉成视频在线观看| 在线 亚洲欧美在线综合一区| 国产精品久久一级| 欧美日韩一区成人| 欧美α欧美αv大片| 久久国产福利| 亚洲综合三区| 一本大道av伊人久久综合| 在线观看日韩av先锋影音电影院| 国产精品视频免费在线观看| 欧美日韩麻豆|