电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

如何使用Javascript中的this關鍵字

瀏覽:3日期:2023-06-20 16:00:04

一、基本的:

function doSomething(){alert(this.id);}alert(window.doSomething);//證明了doSomething是屬于window的doSomething();//undefinedwindow.onload = function(){document.getElementById('div2').onclick = doSomething;//div2document.getElementById('div3').onclick = function(){doSomething();}//undefined}

1、對于doSomething這個函數:

function doSomething(){alert(this.id);}

這個函數是全局函數,這種全局函數實際上是屬于window的(可以通過window.doSomething來訪問),如果直接調用,那么根據“this always refers to the “owner” of the function we’re executing”,那么函數中的this就是window,但是window沒有id屬性,所以顯示“undefined”;

2、在html元素中這樣調用

<div onclick='doSomething();'>div1</div>

這時也會顯示“undefined”,這就相當于如下代碼:

document.getElementById('div1').onclick = function(){doSomething();}

當點擊div1時,調用屬于window的doSomething函數,所以也是顯示“undefined”;

3、通過js來綁定事件,在div2載入過后:

document.getElementById('div2').onclick = doSomething;

當點擊div2時,顯示“div2”,因為在給div2的onclick賦值,是將doSomething拷貝了一次,這時拷貝的這個函數是屬于div2的了,跟屬于window的doSomething沒有任何關系了。點擊div2時,就會觸發屬于div2的doSomething,這里的this就是指div2。

二、attachEvent和addEventListener 

attachEvent是在ie中綁定事件的方法,會將相應函數拷貝到全局(即響應函數的owner為window),但是在DOM標準中,addEventListener綁定的事件時拷貝的響應函數的owner為事件所綁定的對象

function doSomething(){alert(this.id);alert(this == window);}window.onload = function(){var div1 = document.getElementById('div1');if(div1.attachEvent){div1.attachEvent('onclick',doSomething);document.body.appendChild(document.createTextNode('attachEvent'));}else if(div1.addEventListener){div1.addEventListener('click',doSomething,false);document.body.appendChild(document.createTextNode('addEventListener'));}else{div.onclick = doSomething;}}

對于函數doSomething

function doSomething(){alert(this.id);alert(this == window);}

1、使用attachEvent綁定到div1的click事件上,doSometing會被復制到window,這時doSomething里面的this指的是window,點擊div1時會顯示“undefined”和“true”

2、使用addEventListener綁定div1的click事件,這時將doSomething拷貝,這個拷貝過后的函數是屬于div1的,所以點擊div1時會顯示“div1”和“false”,看如下代碼

var obj = new Object();obj.color = 'black';obj.showColor = function(){alert(this.color);alert(this == window);}obj.showColor();var div1 = document.getElementById('div1');div1.attachEvent('onclick',obj.showColor);

此時點擊div1的時候,會顯示“undefined”和“true”,如果attachEvent僅僅是引用obj.showColor的話,那么this還是應該指的是obj,但是實際上這里this指的是window,所以我認為這里不是引用,而是拷貝到全局的。

三、關于對象冒充的繼承方式 

1、new與不new的區別

對于如下function

function ClassA(sColor){this.color = sColor;this.sayColor = function(){alert(this.color);}}

這是一個類還是一個函數?隨你而定!

如果你認為這是一個函數,那么我們可以這樣來調用它:

ClassA('red');

“red”是傳遞的一個參數,ClassA中的this指的是當然就是指的window了,所以現在window有了color屬性和sayColor方法,并且color有“red”這個值。

這是調用sayColor或者window.sayColor都可以顯示“red”;

window.sayColor();

如果你認為這是一個類,那么我們應該這樣使用它:

var obj = new ClassA('red');

new這個關鍵詞的出現讓上面這一句代碼增加了不少內容:首先,創建一個Object實例,然后,將ClassA中的this指向創建的這個Object中,最后返回這個Object,所以返回的這個Object就賦值給了obj。所以我們可以說this指向的是obj,obj擁有了color屬性和sayColor方法,并且color屬性值為“red”。

2、函數的owener

function showId(){alert(this.id);}window.onload = function(){var div1 = document.getElementById('div1');div1.onclick = showId;div1.show = showId;div1.show();var obj = new Object();obj.id = 'obj';obj.show = showId;obj.show();}

我們可以將showId這個函數賦值給click事件,也可以賦值給任何一個對象的任何一個屬性,這是也會拷貝showId這個方法的,所以我們在調用div1.show方法時,this是指向div1的,在調用obj.show時,this指向的是obj的。

3、對象冒充的原理

下面的代碼是通過對象冒充方法實現的繼承

function ClassA(sColor){this.color = sColor;this.sayColor = function(){alert(this.color);}}function ClassB(sColor,sName){this.newMethod = ClassA;this.newMethod(sColor);delete this.newMethod;this.name = sName;this.sayName = function(){alert(this.name);}}var objB = new ClassB('color of objB','name of objB');objB.sayColor();

objB是ClassB的一個實例,objB是如何擁有color屬性和sayColor方法的呢?

首先從實例化的代碼看起:

var objB = new ClassB('color of objB','name of objB');

這里ClassB是個類,ClassB中的this當然就是指的objB這個對象;

在ClassB中,前三行代碼會用到ClassA,這時就把ClassA看作一個函數,而不是類。

我們如果直接調用ClassA這個函數,那么很顯然,ClassA中的this指的就是window對象了,所以我們先將ClassA拷貝到objB的newMethod這個屬性中(this.newMethod = ClassA),

然后再調用this.newMethod,這是這個方法的owener明顯的已經成了this,而ClassB中的this在當前指的是objB,所以此時ClassA中(嚴格的說是newMethod中,因為這是拷貝過后的,跟ClassA已經是兩個方法了)的this就是指的objB,這樣在通過newMethod的調用,就給objB賦值了color屬性和sayColor方法。用call和apply方法來實現繼承實際上也是一個原理,call和apply可以看作是改變方法的owner的方法,而這里ClassB中的前三句代碼也就是起這個作用的。

四、prototype1.6中的Class.create

prototype1.6中的Class.create方法大致如下:

var Class = {create: function() {//function klass() {this.initialize.apply(this, arguments);}//for (var i = 0; i < properties.length; i++)klass.addMethods(properties[i]);//return klass;}};

在使用的時候是這樣的:

var Person = Class.create({initialize:function(name){this.name = name;},say:function(message){alert(this.name + ':' + message);}});var aPerson = new Person('name1');aPerson.say('hello1');

Person實際上是通過Class.create這個方法所返回的klass(klass是Class.create中的局部變量,是一個function),Class.create所傳遞的參數(initialize方法和say方法)傳遞到create方法中的properties數組中并且通過addMethods方法讓klass的prototype擁有這些方法。那么最關鍵的地方也是最難以理解的地方是:klass中的this究竟是指的是什么。仔細想一想就不難得到答案,Person實際上就是klass,而我們在實例化Person對象的時候,是用了new關鍵詞的:

var aPerson = new Person('name1');

這就等價于

var aPerson = new klass('name1');

雖然klass在外面不能被訪問到,但是這樣能很輕易的說明問題,klass是一個類而不是簡單的一個函數(我們看作如此,因為用了new關鍵字),那么klass中的this就指的是聲明的實例,在這里就是aPerson,aPerson通過klass的prototype能夠擁有initialize方法和say方法,在new的過程中,也會執行klass中的代碼,所以initialize在實例化的時候會執行,即構造函數。(在klass里兩個this都是指的aPerson,為什么還要通過apply調用一次呢?這主要是為了傳遞構造函數的參數,用apply方法可以將數目不定的多個參數通過數組方便的傳到initialize方法中去。)

五、再分析幾個例子

從別的文章里看到的例子,我在這里分析一下:

1、運行如下代碼

function OuterFoo(){this.Name = ’Outer Name’;function InnerFoo(){var Name = ’Inner Name’;alert(Name + ’, ’ + this.Name);}return InnerFoo;}OuterFoo()();

所顯示的結果是“Inner Name, Outer Name”

OuterFoo是一個函數(而不是類),那么第一句

this.Name = ’Outer Name’;

中的this指的是window對象,所以OuterFoo()過后window.Name = ‘Outer Name’;

并且將InnerFoo返回,此時InnerFoo同樣是一個函數(不是類),執行InnerFoo的時候,this同樣指window,所以InnerFoo中的this.Name的值為”Outer Name”(window.Name充當了一個中轉站的角色,讓OuterFoo能夠向InnerFoo傳遞“Outer Name”這個值),而Name的值即為局部變量”Inner Name”

2、運行如下代碼

function JSClass(){this.m_Text = ’division element’;this.m_Element = document.createElement(’DIV’);this.m_Element.innerHTML = this.m_Text;if(this.m_Element.attachEvent)this.m_Element.attachEvent(’onclick’, this.ToString);else if(this.m_Element.addEventListener)this.m_Element.addEventListener(’click’, this.ToString,false);elsethis.m_Element.onclick = this.ToString;}JSClass.prototype.Render = function(){document.body.appendChild(this.m_Element);}JSClass.prototype.ToString = function(){alert(this.m_Text);alert(this == window);}window.onload = function(){var jc = new JSClass();jc.Render();jc.ToString();}

點擊“division element”會顯示“undefined”,在ie下還要顯示“true”,其他瀏覽器中還要顯示“false”。

實例聲明和調用實例方法都沒什么可說的,元素的click事件的綁定到了一個實例的方法,那么通過addEventListener綁定到的方法是拷貝過后的,所以this指的是html元素,這個元素沒有m_Text屬性(m_Text屬性是屬于JSClass的實例的,即屬于jc的),所以點擊元素顯示undefined,attachEvent綁定的事件會將函數復制到全局,此時this指的是window對象,點擊元素也會顯示“undefined”。只有在調用jc.ToString()方法是,this指的是jc這個對象,因為jc擁有m_Text,所以能夠顯示“division element”。

六、總結

怎樣在一個代碼環境中快速的找到this所指的對象呢?我想要注意以下三個方面:

1、 要清楚的知道對于函數的每一步操作是拷貝還是引用(調用)

2、 要清楚的知道函數的擁有者(owner)是什么

3、 對于一個function,我們要搞清楚我們是把它當作函數使用還是在當作類使用

補充:

1.在實例和類上都可以直接定義函數

2.不能在實例上使用prototype定義函數,只能在類上使用prototype定義函數

3.類上直接定義的函數不能使用this訪問對象的屬性

4.在類的prototype上建立的函數可以用this,在類內部定義的函數可以使用this,在對象實例上建立的函數額可以this

window.alert=function (msg){document.write(msg+'<br>');}function say(){this.f='props';this.func3=function(){alert('f3,'+this.f);}}say.func1=function(){alert('func1,'+this.f);}; //Error,類上直接定義的函數,不能使用thissay.prototype.func2=function(){alert('func2,'+this.f);}say.func1();(new say()).func2();say.func2(); //Error, 在用prototype定義的函數,必須實例化對象才能調用say.func3(); //Error,在類上定義的函數,必須實例化才能調用(new say()).func3();var obj={fld1:10,func1:function(msg){alert(msg);},func4:function(){alert(this.fld1);}}obj.prototype.func=function(){alert('func');}; //Error 實例對象上不能使用prototype定義對象obj.func2=function(){alert('func2,'+this.fld1);}; //ok,實例上直接定義的函數可以使用this,訪問對象的屬性alert(obj.fld1);obj.func1('func1');obj.func2();obj.func4();

以上就是如何使用Javascript中的this關鍵字的詳細內容,更多關于js this關鍵字的資料請關注好吧啦網其它相關文章!

標簽: JavaScript
相關文章:
主站蜘蛛池模板: 深圳离婚律师咨询「在线免费」华荣深圳婚姻律师事务所专办离婚纠纷案件 | 专业的新乡振动筛厂家-振动筛品质保障-环保振动筛价格—新乡市德科筛分机械有限公司 | 不锈钢/气体/液体玻璃转子流量计(防腐,选型,规格)-常州天晟热工仪表有限公司【官网】 | 卫生纸复卷机|抽纸机|卫生纸加工设备|做卫生纸机器|小型卫生纸加工需要什么设备|卫生纸机器设备多少钱一台|许昌恒源纸品机械有限公司 | 移动厕所租赁|移动卫生间|上海移动厕所租赁-家瑞租赁 | 紧急切断阀_气动切断阀_不锈钢阀门_截止阀_球阀_蝶阀_闸阀-上海上兆阀门制造有限公司 | 济南货架定做_仓储货架生产厂_重型货架厂_仓库货架批发_济南启力仓储设备有限公司 | 集菌仪_智能集菌仪_全封闭集菌仪_无菌检查集菌仪厂家-那艾 | 网带通过式抛丸机,,网带式打砂机,吊钩式,抛丸机,中山抛丸机生产厂家,江门抛丸机,佛山吊钩式,东莞抛丸机,中山市泰达自动化设备有限公司 | 背压阀|减压器|不锈钢减压器|减压阀|卫生级背压阀|单向阀|背压阀厂家-上海沃原自控阀门有限公司 本安接线盒-本安电路用接线盒-本安分线盒-矿用电话接线盒-JHH生产厂家-宁波龙亿电子科技有限公司 | 杭州顺源过滤机械有限公司官网-压滤机_板框压滤机_厢式隔膜压滤机厂家 | 中开泵,中开泵厂家,双吸中开泵-山东博二泵业有限公司 | 无硅导热垫片-碳纤维导热垫片-导热相变材料厂家-东莞市盛元新材料科技有限公司 | 轴流风机-鼓风机-离心风机-散热风扇-罩极电机,生产厂家-首肯电子 | 北京企业宣传片拍摄_公司宣传片制作-广告短视频制作_北京宣传片拍摄公司 | 执业药师报名时间,报考条件,考试时间-首页入口 | 雨燕360体育免费直播_雨燕360免费NBA直播_NBA篮球高清直播无插件-雨燕360体育直播 | 电脑刺绣_绣花厂家_绣花章仔_织唛厂家-[源欣刺绣]潮牌刺绣打版定制绣花加工厂家 | 岩石钻裂机-液压凿岩机-劈裂机-挖改钻_湖南烈岩科技有限公司 | 电动葫芦|防爆钢丝绳电动葫芦|手拉葫芦-保定大力起重葫芦有限公司 | 宁波普瑞思邻苯二甲酸盐检测仪,ROHS2.0检测设备,ROHS2.0测试仪厂家 | 德国进口电锅炉_商用电热水器_壁挂炉_电采暖器_电热锅炉[德国宝] | 粘弹体防腐胶带,聚丙烯防腐胶带-全民塑胶| 仪器仪表网 - 永久免费的b2b电子商务平台 | 转子泵_凸轮泵_凸轮转子泵厂家-青岛罗德通用机械设备有限公司 | 石家庄律师_石家庄刑事辩护律师_石家庄取保候审-河北万垚律师事务所 | 集菌仪_智能集菌仪_全封闭集菌仪_无菌检查集菌仪厂家-那艾 | 包装机传感器-搅拌站传感器-山东称重传感器厂家-济南泰钦电气 | 动物解剖台-成蚊接触筒-标本工具箱-负压实验台-北京哲成科技有限公司 | 冰晶石|碱性嫩黄闪蒸干燥机-有机垃圾烘干设备-草酸钙盘式干燥机-常州市宝康干燥 | 干粉砂浆设备_干混砂浆生产线_腻子粉加工设备_石膏抹灰砂浆生产成套设备厂家_干粉混合设备_砂子烘干机--郑州铭将机械设备有限公司 | 微信聊天记录恢复_手机短信删除怎么恢复_通讯录恢复软件下载-快易数据恢复 | 全自动烧卖机厂家_饺子机_烧麦机价格_小笼汤包机_宁波江北阜欣食品机械有限公司 | 环氧乙烷灭菌器_压力蒸汽灭菌器_低温等离子过氧化氢灭菌器 _低温蒸汽甲醛灭菌器_清洗工作站_医用干燥柜_灭菌耗材-环氧乙烷灭菌器_脉动真空压力蒸汽灭菌器_低温等离子灭菌设备_河南省三强医疗器械有限责任公司 | Eiafans.com_环评爱好者 环评网|环评论坛|环评报告公示网|竣工环保验收公示网|环保验收报告公示网|环保自主验收公示|环评公示网|环保公示网|注册环评工程师|环境影响评价|环评师|规划环评|环评报告|环评考试网|环评论坛 - Powered by Discuz! | 臻知网大型互动问答社区-你的问题将在这里得到解答!-无锡据风网络科技有限公司 | 旋振筛_不锈钢旋振筛_气旋筛_旋振筛厂家—新乡市大汉振动机械有限公司 | 贵州水玻璃_-贵阳花溪闽兴水玻璃厂| 百度爱采购运营研究社社群-店铺托管-爱采购代运营-良言多米网络公司 | 海外仓系统|国际货代系统|退货换标系统|WMS仓储系统|海豚云 | 北京四合院出租,北京四合院出售,北京平房买卖 - 顺益兴四合院 |