1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        再說 this 指向問題

        共 6838字,需瀏覽 14分鐘

         ·

        2021-05-01 10:00

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

        先來看看以下這個(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 全局對象

        為什么呢?

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

        隱式綁定

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

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

        隱式丟失

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

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

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

        一種更微妙、更常見并且更出乎意料的情況發(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 是全局對象的屬性
        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 是全局對象上的屬性
        setTimeout(obj.foo, 100// "oops, global" 也是指向了 window

        顯式綁定

        使用 call,apply,bind 方式來綁定

        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è)原始值(字符串類型、布爾類型或者數(shù)字類型)來當(dāng)作 this 的綁定對象,

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

        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)用場景就是創(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;
        }
        // 簡單的輔助綁定函數(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"

        順便來看看 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 來調(diào)用函數(shù),或者說發(fā)生構(gòu)造函數(shù)調(diào)用時(shí),會自動執(zhí)行下面的操作。

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

        以下是我根據(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)建的過程就綁定了 this 的指向問題,我們可以考慮以下這個(gè)問題:

        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)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产盗摄视频一区二区三区 | 国产精品成人国产乱 | 波多野结衣一区二区三区中文字幕 | 欧美极品aaaaabbbbb | 91嫩|婷婷丨入口图片 | 男女激情上床 | 中文字幕无码人妻二三区免费 | 夜夜免费视频 | 加勒比人妻 | 日韩AV免费看 |