整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          javascript this指向和修改指向的方法

          javascript this指向和修改指向的方法

          源:Loong Panda


          一、不同環(huán)境下的this的指向:


          1、this的指向是在函數(shù)運(yùn)行時確定下來的,而不是創(chuàng)建的時候,誰調(diào)用就指向誰。
          2、ES5中普通函數(shù)this指向window,ES6中普通函數(shù)this指向?yàn)閡ndefined;
          3、事件的this指向,為事件源本身
          4、定時器的this指向,為window.
          5、構(gòu)造函數(shù)內(nèi)部的this指向new出來的這個對象
          
          注: 嚴(yán)格模式下,普通函數(shù)和全局環(huán)境的this為undefined


          1.1 普通函數(shù)和全局環(huán)境下this

          consolog.log(this) // window
          
          function test() { console.log(111, this) // window } test()
          
          注: 'use strict' 嚴(yán)格模式下
          
          consolog.log(this) // undefined
          function test() { console.log(111, this) // undefined } test()


          1.2對象中的this

           let obj3={ 
             say() { 
               console.log(6666, this) // obj3 
               return function () { 
                 console.log(7777, this) // window 
               } 
             } 
           } 
           obj3.say()()

          1.3構(gòu)造函數(shù)內(nèi)的this

          function Person(e) { 
            this.name=e console.log(5555, this) 
          } 
          let a=new Person('李四1') // Person { name: '李四1'} 
          let b=new Person('李四2') // Person { name: '李四2'}


          1.4定時器下的this

          let obj2={ 
            name: '張三', 
            say: function () { 
              console.log(333, this) // obj2 
              setTimeout(function () { 
                console.log(444, this) // window 
              }, 1000)
            } 
          } 
          obj2.say()

          1.5箭頭函數(shù)中的this

          let obj3={ 
            say() { 
              console.log(6666, this) // obj3 
              return ()=> { 
                console.log(7777, this) // obj3 
              } 
            } 
          } 
          obj3.say()()


          二、改變this指向的方法:

          1、箭頭函數(shù) -----> 只適合現(xiàn)代瀏覽器;
          2、bind() -----> 第一個是參數(shù)是指向誰,第二個以后的參數(shù)是自定義的參數(shù),需要單獨(dú)調(diào)用才執(zhí)行,如: bind(obj)()
          3、call(xx, arg1, arg2) -----> 第一個是參數(shù)是指向誰,第二個以后的參數(shù)是自定義的參數(shù)
          4、apply(xx, [arg1, arg2]) -----> 第一個是參數(shù)是指向誰,第二個的參數(shù)是自定義的參數(shù),數(shù)據(jù)類型必須是數(shù)組


          例子

          入淺出 JavaScript 中的 this

          在 Java 等面向?qū)ο蟮恼Z言中,this 關(guān)鍵字的含義是明確且具體的,即指代當(dāng)前對象。一般在編譯期確定下來,或稱為編譯期綁定。而在 JavaScript 中,this 是動態(tài)綁定,或稱為運(yùn)行期綁定的,這就導(dǎo)致 JavaScript 中的 this 關(guān)鍵字有能力具備多重含義,帶來靈活性的同時,也為初學(xué)者帶來不少困惑。本文僅就這一問題展開討論,閱罷本文,讀者若能正確回答 JavaScript 中的 What 's this 問題,那就會覺得花費(fèi)這么多功夫,撰寫這樣一篇文章是值得的。

          1.Java 語言中的 this

          在 Java 中定義類經(jīng)常會使用 this 關(guān)鍵字,多數(shù)情況下是為了避免命名沖突,比如在下面例子的中,定義一個 Point 類,很自然的,大家會使用 x,y 為其屬性或成員變量命名,在構(gòu)造函數(shù)中,使用 x,y 為參數(shù)命名,相比其他的名字,比如 a,b,也更有意義。這時候就需要使用 this 來避免命名上的沖突。另一種情況是為了方便的調(diào)用其他構(gòu)造函數(shù),比如定義在 x 軸上的點(diǎn),其 x 值默認(rèn)為 0,使用時只要提供 y 值就可以了,我們可以為此定義一個只需傳入一個參數(shù)的構(gòu)造函數(shù)。無論哪種情況,this 的含義是一樣的,均指當(dāng)前對象。

          清單 1. Point.java

          2.JavaScript 語言中的 this

          由于其運(yùn)行期綁定的特性,JavaScript 中的 this 含義要豐富得多,它可以是全局對象、當(dāng)前對象或者任意對象,這完全取決于函數(shù)的調(diào)用方式。JavaScript 中函數(shù)的調(diào)用有以下幾種方式:作為對象方法調(diào)用,作為函數(shù)調(diào)用,作為構(gòu)造函數(shù)調(diào)用,和使用 apply 或 call 調(diào)用。下面我們將按照調(diào)用方式的不同,分別討論 this 的含義。

          2.1作為對象方法調(diào)用

          在 JavaScript 中,函數(shù)也是對象,因此函數(shù)可以作為一個對象的屬性,此時該函數(shù)被稱為該對象的方法,在使用這種調(diào)用方式時,this 被自然綁定到該對象。

          清單 2. point.js

          2.2作為函數(shù)調(diào)用

          函數(shù)也可以直接被調(diào)用,此時 this 綁定到全局對象。在瀏覽器中,window 就是該全局對象。比如下面的例子:函數(shù)被調(diào)用時,this 被綁定到全局對象,接下來執(zhí)行賦值語句,相當(dāng)于隱式的聲明了一個全局變量,這顯然不是調(diào)用者希望的。

          清單 3. nonsense.js

          對于內(nèi)部函數(shù),即聲明在另外一個函數(shù)體內(nèi)的函數(shù),這種綁定到全局對象的方式會產(chǎn)生另外一個問題。我們?nèi)匀灰郧懊嫣岬降?point 對象為例,這次我們希望在 moveTo 方法內(nèi)定義兩個函數(shù),分別將 x,y 坐標(biāo)進(jìn)行平移。結(jié)果可能出乎大家意料,不僅 point 對象沒有移動,反而多出兩個全局變量 x,y。

          清單 4. point.js

          這屬于 JavaScript 的設(shè)計(jì)缺陷,正確的設(shè)計(jì)方式是內(nèi)部函數(shù)的 this 應(yīng)該綁定到其外層函數(shù)對應(yīng)的對象上,為了規(guī)避這一設(shè)計(jì)缺陷,聰明的 JavaScript 程序員想出了變量替代的方法,約定俗成,該變量一般被命名為 that。

          清單 5. point2.js

          2.3作為構(gòu)造函數(shù)調(diào)用

          JavaScript 支持面向?qū)ο笫骄幊蹋c主流的面向?qū)ο笫骄幊陶Z言不同,JavaScript 并沒有類(class)的概念,而是使用基于原型(prototype)的繼承方式。相應(yīng)的,JavaScript 中的構(gòu)造函數(shù)也很特殊,如果不使用 new 調(diào)用,則和普通函數(shù)一樣。作為又一項(xiàng)約定俗成的準(zhǔn)則,構(gòu)造函數(shù)以大寫字母開頭,提醒調(diào)用者使用正確的方式調(diào)用。如果調(diào)用正確,this 綁定到新創(chuàng)建的對象上。

          清單 6. Point.js

          2.4使用 apply 或 call 調(diào)用

          讓我們再一次重申,在 JavaScript 中函數(shù)也是對象,對象則有方法,apply 和 call 就是函數(shù)對象的方法。這兩個方法異常強(qiáng)大,他們允許切換函數(shù)執(zhí)行的上下文環(huán)境(context),即 this 綁定的對象。很多 JavaScript 中的技巧以及類庫都用到了該方法。讓我們看一個具體的例子:

          清單 7. Point2.js

          在上面的例子中,我們使用構(gòu)造函數(shù)生成了一個對象 p1,該對象同時具有 moveTo 方法;使用對象字面量創(chuàng)建了另一個對象 p2,我們看到使用 apply 可以將 p1 的方法應(yīng)用到 p2 上,這時候 this 也被綁定到對象 p2 上。另一個方法 call 也具備同樣功能,不同的是最后的參數(shù)不是作為一個數(shù)組統(tǒng)一傳入,而是分開傳入的。

          2.5換個角度理解

          如果像作者一樣,大家也覺得上述四種方式不方便記憶,過一段時間后,又搞不明白 this 究竟指什么。那么我向大家推薦 Yehuda Katz 的這篇文章:( http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/)。在這篇文章里,Yehuda Katz 將 apply 或 call 方式作為函數(shù)調(diào)用的基本方式,其他幾種方式都是在這一基礎(chǔ)上的演變,或稱之為語法糖。Yehuda Katz 強(qiáng)調(diào)了函數(shù)調(diào)用時 this 綁定的過程,不管函數(shù)以何種方式調(diào)用,均需完成這一綁定過程,不同的是,作為函數(shù)調(diào)用時,this 綁定到全局對象;作為方法調(diào)用時,this 綁定到該方法所屬的對象。

          2.6說完了沒?

          通過上面的描述,如果大家已經(jīng)能明確區(qū)分各種情況下 this 的含義,這篇文章的目標(biāo)就已經(jīng)完成了。如果大家的好奇心再強(qiáng)一點(diǎn),想知道為什么 this 在 JavaScript 中的含義如此豐富,那就得繼續(xù)閱讀下面的內(nèi)容了。作者需要提前告知大家,下面的內(nèi)容會比前面稍顯枯燥,如果只想明白 this 的含義,閱讀到此已經(jīng)足夠了。如果大家不嫌枯燥,非要探尋其中究竟,那就一起邁入下一節(jié)吧。

          3.函數(shù)的執(zhí)行環(huán)境

          JavaScript 中的函數(shù)既可以被當(dāng)作普通函數(shù)執(zhí)行,也可以作為對象的方法執(zhí)行,這是導(dǎo)致 this 含義如此豐富的主要原因。一個函數(shù)被執(zhí)行時,會創(chuàng)建一個執(zhí)行環(huán)境(ExecutionContext),函數(shù)的所有的行為均發(fā)生在此執(zhí)行環(huán)境中,構(gòu)建該執(zhí)行環(huán)境時,JavaScript 首先會創(chuàng)建 arguments變量,其中包含調(diào)用函數(shù)時傳入的參數(shù)。接下來創(chuàng)建作用域鏈。然后初始化變量,首先初始化函數(shù)的形參表,值為 arguments變量中對應(yīng)的值,如果 arguments變量中沒有對應(yīng)值,則該形參初始化為 undefined。如果該函數(shù)中含有內(nèi)部函數(shù),則初始化這些內(nèi)部函數(shù)。如果沒有,繼續(xù)初始化該函數(shù)內(nèi)定義的局部變量,需要注意的是此時這些變量初始化為 undefined,其賦值操作在執(zhí)行環(huán)境(ExecutionContext)創(chuàng)建成功后,函數(shù)執(zhí)行時才會執(zhí)行,這點(diǎn)對于我們理解 JavaScript 中的變量作用域非常重要,鑒于篇幅,我們先不在這里討論這個話題。最后為 this變量賦值,如前所述,會根據(jù)函數(shù)調(diào)用方式的不同,賦給 this全局對象,當(dāng)前對象等。至此函數(shù)的執(zhí)行環(huán)境(ExecutionContext)創(chuàng)建成功,函數(shù)開始逐行執(zhí)行,所需變量均從之前構(gòu)建好的執(zhí)行環(huán)境(ExecutionContext)中讀取。

          3.1 Function.bind

          有了前面對于函數(shù)執(zhí)行環(huán)境的描述,我們來看看 this 在 JavaScript 中經(jīng)常被誤用的一種情況:回調(diào)函數(shù)。JavaScript 支持函數(shù)式編程,函數(shù)屬于一級對象,可以作為參數(shù)被傳遞。請看下面的例子 myObject.handler 作為回調(diào)函數(shù),會在 onclick 事件被觸發(fā)時調(diào)用,但此時,該函數(shù)已經(jīng)在另外一個執(zhí)行環(huán)境(ExecutionContext)中執(zhí)行了,this 自然也不會綁定到 myObject 對象上。

          清單 8. callback.js

          button.onclick=myObject.handler;

          這是 JavaScript 新手們經(jīng)常犯的一個錯誤,為了避免這種錯誤,許多 JavaScript 框架都提供了手動綁定 this 的方法。比如 Dojo 就提供了 lang.hitch,該方法接受一個對象和函數(shù)作為參數(shù),返回一個新函數(shù),執(zhí)行時 this 綁定到傳入的對象上。使用 Dojo,可以將上面的例子改為:

          清單 9. Callback2.js

          button.onclick=lang.hitch(myObject, myObject.handler);

          在新版的 JavaScript 中,已經(jīng)提供了內(nèi)置的 bind 方法供大家使用。

          3.2 eval 方法

          JavaScript 中的 eval 方法可以將字符串轉(zhuǎn)換為 JavaScript 代碼,使用 eval 方法時,this 指向哪里呢?答案很簡單,看誰在調(diào)用 eval 方法,調(diào)用者的執(zhí)行環(huán)境(ExecutionContext)中的 this 就被 eval 方法繼承下來了。簡單看個eval示例:

          4.結(jié)語

          本文介紹了 JavaScript 中的 this 關(guān)鍵字在各種情況下的含義,雖然這只是 JavaScript 中一個很小的概念,但借此我們可以深入了解 JavaScript 中函數(shù)的執(zhí)行環(huán)境,而這是理解閉包等其他概念的基礎(chǔ)。掌握了這些概念,才能充分發(fā)揮 JavaScript 的特點(diǎn),才會發(fā)現(xiàn) JavaScript 語言特性的強(qiáng)大。

          6 - 27 - 箭頭函數(shù):基礎(chǔ) & this 關(guān)鍵字

          原文:https://dev.to/bhagatparwinder/arrow-function-basics-34cm

          簡介

          箭頭函數(shù)是在 ES6 引入的,相對于函數(shù)表達(dá)式來說是一種更簡潔的方式。

          箭頭函數(shù)名稱的來源是因?yàn)槭褂昧?=>

          語法

          const functionName = (arg1, arg2, ... argN) => {
              return value;
          }

          例子

          const multiply = (a, b) => {
              return a * b;
          }
          console.log(multiply(7, 8)); // 56
          console.log(multiply(3, 2)); // 6

          關(guān)鍵特點(diǎn)

          • ? 箭頭函數(shù)類似匿名函數(shù)
          • ? 若只有一個參數(shù),可以省略小括號
             const square = x => {
                 return x * x;
             }
             console.log(square(2)); // 4
             console.log(square(7)); // 49

          這個情形的唯一陷阱是當(dāng)只有一個參數(shù)且需要解構(gòu)時:

              const foo = ({name = "New User"}) => name;
              
              console.log(foo({})); // New User
              console.log(foo({name: "Parwinder"})); // Parwinder
          • ? 若沒有參數(shù),需要添加上小括號
             const greeting = () => {
                 return "Hello World!";
             }
             console.log(greeting()); // Hello World!
          • ? 若函數(shù)體是一個表達(dá)式且只返回該表達(dá)式,我們可以移出小括號和 return 關(guān)鍵字。
             const greeting = () => "Hello World!";
             console.log(greeting()); // Hello World

          現(xiàn)在我們知道了所有的關(guān)鍵特點(diǎn),讓我們來重寫獲取正方形的面積:

          const square = x => x * x;
          console.log(square(4)); // 16

          this 關(guān)鍵字

          this 關(guān)鍵字和函數(shù)

          JavaScript 中的 this 關(guān)鍵字是執(zhí)行上下文的一個屬性,它可能是全局的、函數(shù)內(nèi)的或者是 eval 中的。對于普通的函數(shù),this 會根據(jù)調(diào)用它方式不同而變化。

          1. 1. 函數(shù)直接調(diào)用時,this 指向全局對象;
          2. 2. 用在構(gòu)造函數(shù)中,this 代表一個新對象;
          3. 3. 當(dāng)函數(shù)作為一個對象的方法被調(diào)用,this 就代表那個對象;
          4. 4. 在嚴(yán)格模式下, this 的值為 undefined;
          5. 5. 在事件中,this 指向接收到事件的元素;

          我們使用這種行為已經(jīng)很久了,以至于大多數(shù)JavaScript開發(fā)者都已經(jīng)習(xí)慣了。

          函數(shù)直接調(diào)用,this 代表全局對象

          function foo() {
              return this;
          };
          console.log(foo()); // window object in a browser, global object for node execution

          用在構(gòu)造函數(shù)中,this 代表一個新對象

          function Order(main, side, dessert) {
              this.main = main;
              this.side = side;
              this.dessert = dessert;
              this.order = function () {
                  return `I will have ${this.main} with ${this.side} and finish off with a ${this.dessert}`;
              }
          }
          const newOrder = new Order("sushi", "soup", "yogurt");
          console.log(newOrder.order());
          // I will have sushi with soup and finish off with a yogurt

          當(dāng)函數(shù)作為一個對象的方法被調(diào)用,this 就代表那個對象

          const myObject = {
              main: "butter chicken",
              side: "rice",
              dessert: "ice cream",
              order: function () {
                  return `I will have ${this.main} with ${this.side} and finish off with ${this.dessert}`;
              }
          }
          console.log(myObject.order());
          // I will have butter chicken with rice and finish off with ice cream

          上面的例子中,this 指向 myObject,可以獲取它上面的屬性。

          在嚴(yán)格模式下, this 的值為 undefined

          "use strict";
          function foo() {
              return this;
          };
          console.log(foo() === undefined); // true

          在事件中,this 指向接收到事件的元素


          主站蜘蛛池模板: 精品人妻中文av一区二区三区| 国产一区三区二区中文在线| 日本一区视频在线播放| 日本一区高清视频| 精品一区二区三区水蜜桃| 亚洲成av人片一区二区三区| 精品国产一区二区三区在线观看| 日韩制服国产精品一区| 亚洲电影一区二区| 韩国资源视频一区二区三区| 一区二区三区在线播放视频| 国产精品高清一区二区三区 | 丰满少妇内射一区| 久久国产精品无码一区二区三区| 国产精品久久无码一区二区三区网| 亚洲日韩激情无码一区| 久久精品一区二区三区AV| 视频一区二区在线观看| 国产在线精品一区二区中文| 亚洲日韩精品国产一区二区三区| 视频一区二区中文字幕| 色偷偷一区二区无码视频| 成人精品一区久久久久| 国产免费一区二区视频| 亚洲av日韩综合一区二区三区| 国产精品第一区第27页| 中文字幕一区二区三区在线观看| 国产精品一区二区无线| 亚洲国产一区国产亚洲 | 中文字幕一区二区在线播放 | 91精品一区二区综合在线| 日本一区二区三区四区视频| 日韩精品一区二区三区大桥未久| 鲁丝丝国产一区二区| 一区二区视频在线播放| 亚州国产AV一区二区三区伊在| 精品国产鲁一鲁一区二区| 任你躁国产自任一区二区三区| 欧美日韩精品一区二区在线观看 | 久久精品亚洲一区二区| 国产三级一区二区三区|