1. 程式人生 > 其它 >題解 SP10606 【BALNUM - Balanced Numbers】

題解 SP10606 【BALNUM - Balanced Numbers】

1. this的涵義,this是什麼

  • 不管是什麼場合,this都有一個共同點:它總是返回一個物件;簡單說,this就是屬性或方法“當前”所在的物件。
  • JavaScript 語言之中,一切皆物件,執行環境也是物件,所以函式都是在某個物件之中執行,this就是函式執行時所在的物件(環境)。

2. this的設計目的

  • 由於函式可以在不同的執行環境執行,所以需要有一種機制,能夠在函式體內部獲得當前的執行環境(context)。所以,this就出現了,它的設計目的就是在函式體內部,指代函式當前的執行環境。

3. 使用場合,使用注意事項

  • 使用場合
  1. 全域性環境:全域性環境使用this,它指的就是頂層物件window。
  2. 建構函式。
  3. 物件的方法:JavaScript 引擎內部,obj和obj.foo儲存在兩個記憶體地址,稱為地址一和地址二。obj.foo()這樣呼叫時,是從地址一呼叫地址二,因此地址二的執行環境是地址一,this指向obj。但是,如果是直接取出地址二進行呼叫,這樣的話,執行環境就是全域性環境,因此this指向全域性環境。
  • 注意事項
  1. 避免多層this
var o = {
  f1: function () {
    console.log(this);
    var f2 = function () {
      console.log(this);
    }();
  }
}

o.f1()
// Object // Window // 實際執行的是下面的程式碼。 var temp = function () { console.log(this); }; var o = { f1: function () { console.log(this); var f2 = temp(); } } // 嚴格模式下,如果函式內部的this指向頂層物件,就會報錯。 var counter = { count: 0 }; counter.inc = function () { 'use strict'; this.count++ }; var f = counter.inc; f()
// TypeError: Cannot read property 'count' of undefined

2.避免陣列處理方法中的 this

var o = {
  v: 'hello',
  p: [ 'a1', 'a2' ],
  f: function f() {
    this.p.forEach(function (item) {
      console.log(this.v + ' ' + item);
    });
  }
}

o.f()
// undefined a1
// undefined a2

// 上面程式碼中,foreach方法的回撥函式中的this,其實是指向window物件,因此取不到o.v的值。

// 將this當作foreach方法的第二個引數,固定它的執行環境。

var o = {
  v: 'hello',
  p: [ 'a1', 'a2' ],
  f: function f() {
    this.p.forEach(function (item) {
      console.log(this.v + ' ' + item);
    }, this);
  }
}

o.f()
// hello a1
// hello a2

3.避免回撥函式中的 this

var o = new Object();
o.f = function () {
  console.log(this === o);
}

// jQuery 的寫法
$('#button').on('click', o.f);

// 上面程式碼中,點選按鈕以後,控制檯會顯示false。原因是此時this不再指向o物件,而是指向按鈕的 DOM 物件

4. 繫結this的方法

  • Function.prototype.call()
var obj = {};

var f = function () {
  return this;
};

f() === window // true
f.call(obj) === obj // true

// call方法還可以接受多個引數。

func.call(thisValue, arg1, arg2, ...)

//call的第一個引數就是this所要指向的那個物件,後面的引數則是函式呼叫時所需的引數。
  • Function.prototype.apply()
// apply方法的作用與call方法類似,也是改變this指向,然後再呼叫該函式。唯一的區別就是,它接收一個數組作為函式執行時的引數。

// 1. 找出陣列最大元素
var a = [10, 2, 4, 15, 9];
Math.max.apply(null, a) // 15

// 2. 將陣列的空元素變為undefined,空元素與undefined的差別在於,陣列的forEach方法會跳過空元素,但是不會跳過undefined。
Array.apply(null, ['a', ,'b'])
// [ 'a', undefined, 'b' ]

// 3. 轉換類似陣列的物件。
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]
// 從上面程式碼可以看到,這個方法起作用的前提是,被處理的物件必須有length屬性,以及相對應的數字鍵。

// 4. 繫結回撥函式的物件
var o = new Object();

o.f = function () {
  console.log(this === o);
}

var f = function (){
  o.f.apply(o);
  // 或者 o.f.call(o);
};

// jQuery 的寫法
$('#button').on('click', f);
  • Function.prototype.bind()
// bind()方法用於將函式體內的this繫結到某個物件,然後返回一個新函式。

var counter = {
  count: 0,
  inc: function () {
    this.count++;
  }
};

var func = counter.inc.bind(counter);
func();
counter.count // 1