題解 SP10606 【BALNUM - Balanced Numbers】
阿新 • • 發佈:2021-06-23
1. this的涵義,this是什麼
- 不管是什麼場合,this都有一個共同點:它總是返回一個物件;簡單說,this就是屬性或方法“當前”所在的物件。
- JavaScript 語言之中,一切皆物件,執行環境也是物件,所以函式都是在某個物件之中執行,this就是函式執行時所在的物件(環境)。
2. this的設計目的
- 由於函式可以在不同的執行環境執行,所以需要有一種機制,能夠在函式體內部獲得當前的執行環境(context)。所以,this就出現了,它的設計目的就是在函式體內部,指代函式當前的執行環境。
3. 使用場合,使用注意事項
- 使用場合
- 全域性環境:全域性環境使用this,它指的就是頂層物件window。
- 建構函式。
- 物件的方法:JavaScript 引擎內部,obj和obj.foo儲存在兩個記憶體地址,稱為地址一和地址二。obj.foo()這樣呼叫時,是從地址一呼叫地址二,因此地址二的執行環境是地址一,this指向obj。但是,如果是直接取出地址二進行呼叫,這樣的話,執行環境就是全域性環境,因此this指向全域性環境。
- 注意事項
- 避免多層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