刷題-5

刷題-5 bind 相關問題

題目1

function f() {
  console.log(this);
}
let f1 = f.bind(1).bind(2)
f1()

複製代碼

解析:javascript

  • bind 基本實現(不完整)
Function.prototype.bind = function (thisArg) {
    var _this = this
    return function () {
        _this.apply(thisArg)
    }
}

複製代碼
  • bind 原理:java

    bind的原理, bind的做用是永久改變一個函數執行過程當中的this,它的基本實現
    
     bind的執行不會當即執行須要改變this指向的函數
    
      bind執行後返回一個新函數
    
      新函數調用會間接調用源函數來實現源函數的執行
    
      函數執行過程當中經過apply(apply、call)把this指向thisArg 閉包:
    
      內層函數能夠訪問外層數據 內層:return 後面的函數    外層:bind函數阻止垃圾回收,
      因此即便bind已經執行完成了,可是由於return的函數被外部引用,
      因此bind中的thisArg並無被回收,
      這樣後續不管何時調用return出去的函數都能訪問到thisArg
    複製代碼
  • 因此:閉包

function f() {
      console.log(this);
    }
    let f1 = f.bind(1).bind(2);
    f1();
    
    // 其實能夠當作下面的調用
    
    let temp = f.bind(1);
    let f1 = temp.bind(2);
    f1();
    
    首先 temp 是 f.bind(1) 的結果
    temp = function(1) {
        // 這裏的 thisArg = 1
        function() {
            f.apply(1);
        }
    }
    
    //也就是temp調用的時候接收了一個1的參數,而後間接的調用了f,並把f的this指向了temp的參數1
    //而後 let f1 = temp.bind(2) 執行之後 f1 代碼
    f1 = function(2) {
    // 這裏的 thisArg = 2
    function() {
        temp.apply(2);
        }
    }

    // f1調用的時候接收了一個2的參數,而後間接的調用了temp,並把temp的this指向了2

複製代碼
  • 重點:

其實這裏特別注意的是其實f1調用了temp並確實改了temp的this爲2,可是這裏是沒有調用最開始的f的,而是temp.apply(2)的時候再去調用的f.apply(2),因此不管中間有多少層bind,最後那個f調用永遠都是最開始的1app

let temp = f.bind(1);
let f1 = temp.bind(2);
let f2 = f1.bind(3);
let f3 = f2.bind(4);
let f4 = f3.bind(5);
f4();

f4() => f3.apply(5) => f2.apply(4) => f1.apply(3) => temp.apply(2)=>f.apply(1)

複製代碼

就是bind一次包一層函數,每一次都有本身的this指向,最後一次執行的也就是最開始bind的纔會執行初始綁定的函數,改變它的this.函數

題目 2

function f() {
 console.log(typeof this);
}
let f1 = f.bind(1).bind(2)
let val = f1() // object

複製代碼
  • 重點:

this 永遠必須是個 對象,不能是其餘類型,雖然不能直接賦值,可是能夠經過callapplybind 內部改變 this,可是爲了確保 this 爲對象類型,若是賦給他的值是非對象的,則會轉成對象post

  • 解析:ui

    • Number、String、Boolean 是 javascript 內置的三個基本類型包裝對象
    • null 和 undefined 沒有對象包裝對象(類) this 指向將不會改變,等同於 f() 直接調用
function f() {
  console.log(typeof this, this);
}

f.call(0)
// object Number {0} 實際上是: new Number(0)

f.call('hello world')  
// object String {"hello world"} 實際上是: new String('hello world')

f.call(true)
// object String {"hello world"} 實際上是: new Boolean(true)

f.call(null)
// object Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}

f.call(undefined)
// object Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
複製代碼
相關文章
相關標籤/搜索