1. 程式人生 > 其它 >保潔阿姨看完都會了!Flutter盡然還能有這種操作!移動架構師成長路線

保潔阿姨看完都會了!Flutter盡然還能有這種操作!移動架構師成長路線

普通函式執行

  • 自執行函式this指向window
  • 如果普通函式執行,前面沒有"."this指向window,如果前面有“.”的話,“.”前面是誰this就是誰
    function fn() {
        console.log(this)
    }
    let obj
    = { name: 'zhangshan', fn: fn } fn() // window obj.fn() // obj

建構函式執行

  • 建構函式執行,函式中的this指向的是當前類的例項
    function fn() { 
       console.log(this)     // fn
    }
    let f = new
    fn()

事件繫結方法

  • 給元素的某個事件行為繫結方法,事件觸發,方法執行些時方法中的this一般指向當前物件元素。
  • DOM0
    btn.onclick = function() {
      console.log(this)   // btn  
    }
  • DOM2
    btn.addEventListener('click',function() {
        console.log(this)    // btn
    }, false)
    btn.attachEvent('click',function() {
       // IE8瀏覽器中的DOM2事件繫結
        console.log(this)    //
    window }, false)

箭頭函式

  • 箭頭函式中沒有自身的this,所用到this都是其上下文中的this
    let  obj = {
      fn: ()=> {
          consloe.log(this)    // window     
      }  
    }    
  • 箭頭函式沒有的東西
    • prototype,所以不能被new函式
    • 沒有arguments實參集合(可以基於...args剩餘運算獲取)
      let obj = {
        fn:(...arg) => {
          console.log(args)
        }  
      }

可以改變this的指向的方法

    • call方法執行的時候,會把[function]執行,並且把函式中的THIS指向為[context],並且把params1,params2…等引數值分別傳遞給函式。
      var
      obj = {}; var f = function () { return this; }; f() === window // true f.call(obj) === obj. // true
    • call方法的引數,應該是一個物件。如果引數為空、nullundefined,則預設傳入全域性物件。
      var n = 123;
      var obj = { n: 456 };
      
      function a() {
        console.log(this.n);
      }
      
      a.call() // 123
      a.call(null) // 123
      a.call(undefined) // 123
      a.call(window) // 123
      a.call(obj) // 456
    • call可以傳人多個引數
      fn.call(obj, arg1, arg2, arg3, ....)
      call的第一個引數就是this所要指向的那個物件,後面的引數則是函式呼叫時所需的引數
      function add(a, b) {
        reurn a + b  
      }
      fn.call(this, 1, 2) // 3
    • call方法的一個應用是呼叫物件的原生方法

      var obj = {};
      obj.hasOwnProperty('toString') // false
      
      // 覆蓋掉繼承的 hasOwnProperty 方法
      obj.hasOwnProperty = function () {
        return true;
      };
      obj.hasOwnProperty('toString') // true
      
      Object.prototype.hasOwnProperty.call(obj, 'toString') // false
    • call方法實現原理
      Function.prototype.myCall = function(context = window, ...args) {
        // context如果沒傳是window
        // 但如果傳了,且並非是物件,怎麼辦?比如:String,Boolean等,但不包含Array、Function等
        context = context instanceof Object ? context : {}
        // 在上下文中執行fn方法,保證執行環境是context
        context.fn = this
        const result = context.fn(...args)
        // 原生call是不會汙染context的,所以這裡要刪除掉
        delete context.fn
        // 返回執行結果
        return result
      }
  • apply
    • apply方法的作用與call方法類似,也是改變this指向,然後再呼叫該函式。唯一的區別就是,它接收一個數組作為函式執行時的引數
      func.apply(thisValue, [arg1, arg2, ...])
    • apply的一些應用
      • 找出陣列最大元素
        let arr = [10, 2, 4, 15, 9];
        Math.max.apply(null, arr)
      • 將陣列的空元素變為undefined
        Array.apply(null, ['a', ,'b'])
        // [ 'a', undefined, 'b' ]
      • 轉換類似陣列的物件
        Array.prototype.slice.apply({0: 1, length: 1}) // [1]
        Array.prototype.slice.apply({0: 1}) // []
        Array.prototype.slice.apply({0: 1, length: 2}) // [1, undefined]
        Array.prototype.slice.apply({length: 1}) // [undefined]
    • apply實現原理
      Function.prototype.myApply = function(context=window, arg) {
        context.fn = this;
      let result = context.fn(arg)
      delete context.fn return result; }
  • bind
    • bind()方法用於將函式體內的this繫結到某個物件,然後返回一個新函式。
    • call/apply都是把當前函式立即執行,並且改變函式中的this指向的,而bind是一個預處理的思想
    • 基於bind只是預先把函式中的this指向[context],把params這些引數值預先儲存起來,但是此時函式並沒有被執行
    • bind的實現原理
      Function.prototype.myBind = function(context = window, ...args) {
        const fn = this;
        return function() {
          return fn.apple(context, [...args, ...arguments])
       }
      }