<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          再說(shuō) this 指向問(wèn)題

          共 6838字,需瀏覽 14分鐘

           ·

          2021-05-01 10:00

          要知道 this 指向問(wèn)題,需要知道函數(shù)調(diào)用棧,函數(shù)調(diào)用的位置。

          先來(lái)看看以下這個(gè)例子:

          function baz({
              // 當(dāng)前調(diào)用棧:baz
              // 因此,當(dāng)前調(diào)用位置是全局作用域

              console.log("baz")
              bar(); // bar 的調(diào)用位置
          }

          function bar({
              // 當(dāng)前調(diào)用棧是 baz -> bar
              // 因此,當(dāng)前調(diào)用位置在 baz

              console.log("bar")
              foo(); // foo 調(diào)用位置
          }

          function foo({
              // 當(dāng)前調(diào)用棧是 baz -> bar -> foo
              // 因此,當(dāng)前調(diào)用位置在 bar 中
              console.log("foo")
          }

          baz() // baz 的調(diào)用位置

          綁定規(guī)則

          獨(dú)立函數(shù)調(diào)用

          function foo({
            console.log(this.a)
          }

          var a = 10
          foo() // 10

          在本例子中 this 默認(rèn)指向了 window 全局對(duì)象

          為什么呢?

          因?yàn)椋瘮?shù)調(diào)用時(shí)不帶其他修飾的函數(shù)調(diào)用,使用默認(rèn)綁定 this 到全局 window 對(duì)象上。

          隱式綁定

          非嚴(yán)格模式下,函數(shù)調(diào)用 this 指向調(diào)用者。

          function foo({
           console.log( this.a );
          }
          var obj = {
           a2,
           foo: foo
          };
          obj.foo(); // 2

          隱式丟失

          把 this 綁定到全局對(duì)象或者 undefined 上,取決于是否是嚴(yán)格模式。

          function foo({
           console.log( this.a );
          }
          var obj = {
           a2,
           foo: foo
          };
          var bar = obj.foo; // 函數(shù)別名!

          var a = "oops, global"// a 是全局對(duì)象的屬性
          bar(); // "oops, global" 調(diào)用的位置是在全局對(duì)象上的,所以 this 指向了 window

          一種更微妙、更常見(jiàn)并且更出乎意料的情況發(fā)生在傳入回調(diào)函數(shù)時(shí):

          function foo({
           console.log( this.a );
          }
          function doFoo(fn{
           // fn 其實(shí)引用的是 foo
           fn(); // <-- 調(diào)用位置!
          }
          var obj = {
           a2,
           foo: foo
          };
          var a = "oops, global"// a 是全局對(duì)象的屬性
          doFoo( obj.foo ); // "oops, global" 實(shí)際上 this 也是指向 window 的

          將函數(shù)傳入內(nèi)置函數(shù)呢:

          function foo({
              console.log( this.a );
          }

          var obj = {
              a:2,
              foo:foo
          }

          var a = "oops, global"// a 是全局對(duì)象上的屬性
          setTimeout(obj.foo, 100// "oops, global" 也是指向了 window

          顯式綁定

          使用 call,apply,bind 方式來(lái)綁定

          function foo({
           console.log( this.a );
          }
          var obj = {
           a:2
          };
          foo.call( obj ); // 2

          上面這種方式就好像下面這樣定義,只是換了一種方式

          function foo(){
            console.log(this.a)
          }

          var obj = {
            a2,
            foo: foo
          }

          obj.foo() // 2

          如果你傳入了一個(gè)原始值(字符串類(lèi)型、布爾類(lèi)型或者數(shù)字類(lèi)型)來(lái)當(dāng)作 this 的綁定對(duì)象,

          這個(gè)原始值會(huì)被轉(zhuǎn)換成它的對(duì)象形式(也就是 new String(..)new Boolean(..) 或者 new Number(..))。這通常被稱(chēng)為“裝箱”。

          function foo({
           console.log( this.a );
          }
          var obj = {
           a:2
          };
          foo.call( 2 ); // undefined

          硬綁定

          function foo({
              console.log( this.a )
          }

          var obj = {
              a:2
          }

          var bar = function({
              foo.call(obj)
          }

          bar() // 2

          setTimeout(bar, 100// 2

          硬綁定的典型應(yīng)用場(chǎng)景就是創(chuàng)建一個(gè)包裹函數(shù),負(fù)責(zé)接收參數(shù)并返回值:

          function foo(something{
              console.log(this.a, something)
              return this.a + something
          }

          var obj = {
              a2
          }

          var bar = function({
              return foo.apply(obj, arguments)
          }

          var b = bar(3// 2 3
          console.log(b) // 5

          另一種使用方法是創(chuàng)建一個(gè)可以重復(fù)使用的輔助函數(shù):

          function foo(something{
           console.log( this.a, something );
           return this.a + something;
          }
          // 簡(jiǎn)單的輔助綁定函數(shù)
          function bind(fn, obj{
           return function({
              return fn.apply( obj, arguments );
           };
          }
          var obj = {
           a:2
          };
          var bar = bind( foo, obj );
          var b = bar( 3 ); // 2 3
          console.log( b ); // 5

          es6 提供的 bind 方法

          function foo(something{
              console.log( this.a, something );
              return this.a + something;
          }

          var obj = {
              a2
          }

          var bar = foo.bind(obj)

          var b = bar(3// 2 3

          console.log(b) // 5

          循環(huán)中的 this 綁定

          function foo(el{
              console.log(el, this.id)
          }

          var obj = {
              id"awesome"
          }

          var arr = [1,2,3]

          arr.forEach(foo, obj);

          // 1 "awesome"
          // 2 "awesome"
          // 3 "awesome"

          順便來(lái)看看 forEach, map 的核心區(qū)分:

          function foo(el{
              console.log(el, this.id)
          }

          var obj = {
              id"awesome"
          }

          var arr = [1,2,3]

          var res = arr.map(foo, obj);

          console.log("map===>", res)


          var eachRes = arr.forEach(foo, obj)

          console.log("each===>", eachRes)


          // 1 "awesome"
          // 2 "awesome"
          // 3 "awesome"
          // map===> (3) [undefined, undefined, undefined] // 返回?cái)?shù)組
          // 1 "awesome"
          // 2 "awesome"
          // 3 "awesome"
          // each===> undefined // 返回undefined

          new 操作

          使用 new 來(lái)調(diào)用函數(shù),或者說(shuō)發(fā)生構(gòu)造函數(shù)調(diào)用時(shí),會(huì)自動(dòng)執(zhí)行下面的操作。

          • 創(chuàng)建(或者說(shuō)構(gòu)造)一個(gè)全新的對(duì)象。
          • 這個(gè)新對(duì)象會(huì)被執(zhí)行 [[Prototype]] 連接。
          • 這個(gè)新對(duì)象會(huì)綁定到函數(shù)調(diào)用的 this。
          • 如果函數(shù)沒(méi)有返回其他對(duì)象,那么 new 表達(dá)式中的函數(shù)調(diào)用會(huì)自動(dòng)返回這個(gè)新對(duì)象。

          以下是我根據(jù)上面這個(gè)思路實(shí)現(xiàn)的代碼

          function newOP(fn{
              var obj = Object.create(null)
              var fnProto = Object.create(fn.__proto__)
              obj.__proto__ = fnProto

              var res = fn.apply(obj, arguments)

              return res ? res : obj
          }

          this詞法

          箭頭函數(shù)在創(chuàng)建的過(guò)程就綁定了 this 的指向問(wèn)題,我們可以考慮以下這個(gè)問(wèn)題:

          function foo({
           // 返回一個(gè)箭頭函數(shù)
           return (a) => {
           //this 繼承自 foo()
           console.log( this.a );
           };
          }
          var obj1 = {
           a:2
          }; 

          var obj2 = {
           a:3
          }

          var bar = foo.call(obj1)
          bar.call(obj2); // 2 而不是 3

          箭頭函數(shù)最常用于回調(diào)函數(shù)中,例如事件處理器或者定時(shí)器:

          function foo({
           setTimeout(() => {
           // 這里的 this 在詞法上繼承自 foo()
           console.log( this.a );
           },100);
          }
          var obj = {
           a:2
          };
          foo.call( obj ); // 2


          瀏覽 65
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产小黄片在线播放 | 亚洲伊人久久久 | 亚洲娇小wite黑人粗大 | 色老太老太色CD | 亚洲成人热区 |