[TOC]
# 1. this關鍵字
JavaScript中的this指向問題,有時候會讓人難以捉摸,隨著學習的深入,我們可以逐漸了解,函數內部的this有如下幾個特點:
1. 函數在定義的時候this是不確定的,只有在調用的時候才可以確定
2. 一般函數直接執行,內部this指向全局window
3. 函數作為一個對象的方法,被該對象所調用,那么this指向的是該對象
4. 構造函數中的this其實是一個隱式對象,類似一個初始化的模型,所有方法和屬性都掛載到了這個隱式對象身上,后續通過new關鍵字來調用,從而實現實例化
| 調用方式 | 非嚴格模式 | 備注 |
| --- | --- | --- |
| 普通函數調用 | window | 嚴格模式下是 undefined |
| 構造函數調用 | 實例對象 | 原型方法中 this 也是實例對象 |
| 對象方法調用 | 該方法所屬對象 | 緊挨著的對象 |
| 事件綁定方法 | 綁定事件對象 | |
| 定時器函數 | window |
# 2. call、apply、bind函數
call、apply、bind函數可以將`this`指向規定的對象。
<mark>1. call函數</mark>
語法:
```js
fun.call(thisArg[, arg1[, arg2[, ...]]]) //[ ] 表示可選, fun為函數
```
注意:該方法的作用和 apply() 方法類似,只有一個區別,就是 call() 方法接受的是若干個參數的列表,而 apply() 方法接受的是一個包含多個參數的數組。
- `thisArg`
+ 在 fun 函數運行時指定的 this 值
+ 如果指定了 null 或者 undefined 則內部 this 指向 window
+ 值為原始值(數字,字符串,布爾值)的`this`會指向該原始值的自動包裝對象。
- `arg1, arg2, ...`
* 指定的參數列表
* 返回值
* 返回值是你調用的方法的返回值,若該方法沒有返回值,則返回`undefined`
```js
function fun1(x, y) {
console.log(x+y);
}
var message = {
name: "李明",
age: 24
}
// call函數調用了fun1函數
// fun1的this指向了message對象
// 100,200兩個實參對應fun1的兩個形參
fun1.call(message, 100, 200); // 300
```
<mark>2. apply函數</mark>
語法:
```js
fun.apply(thisArg, [argsArray])
```
`apply()` 與 `call()` 非常相似,不同之處在于提供參數的方式。`apply()` 使用參數數組而不是一組參數列表。例如:
```js
fun.apply(this, ['eat', 'bananas'])
```
<mark>3. bind函數</mark>
bind() 函數會創建一個新函數(稱為綁定函數),新函數與被調函數具有相同的函數體(在 ECMAScript 5 規范中內置的call屬性)。
當 ```fun.bind(thisArg,..)時,``` ```fun的this``` 綁定到 bind() 的第一個參數,該參數不能被重寫。綁定函數被調用時,bind() 也接受預設的參數提供給原函數,即```fun```。
一個綁定函數也能使用new操作符創建對象:這種行為就像把原函數當成構造器。提供的 ```this``` 值被忽略,同時調用時的參數被提供.
```js
function f1(x, y) {
console.log(x+y);
}
var obj = {
age: 10,
getAge: function() {
console.log(this.age);
}
}
// f1的this指向了obj
// 100,200兩個實參對應f1中的兩個形參
// bind函數返回了ff函數,結構與f1一樣
// bind函數并沒有調用f1函數,所以f1.bind不會執行f1的代碼
var ff = f1.bind(obj, 100, 200); // ff就是綁定函數
ff(); // 300 調用ff時上面的那兩個實參100,200也提供給了ff
```
語法:
```js
fun.bind(thisArg[, arg1[, arg2[, ...]]])
```
- thisArg
+ 當綁定函數被調用時,該參數會作為原函數運行時的 this 指向。當使用new 操作符調用綁定函數時,該參數無效。
- arg1, arg2, ...
+ 當綁定函數被調用時,這些參數將置于實參之前傳遞給被綁定的方法。
返回值:返回由指定的this值和初始化參數改造的原函數拷貝。
實例1:
```js
this.x = 9;
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 返回 81
var retrieveX = module.getX;
retrieveX(); // 返回 9, 在這種情況下,"this"指向全局作用域
// 創建一個新函數,將"this"綁定到module對象
// 新手可能會被全局的x變量和module里的屬性x所迷惑
var boundGetX = retrieveX.bind(module);
boundGetX(); // 返回 81
```
實例2:
```js
function LateBloomer() {
this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.declare = function() {
console.log('I am a beautiful flower with ' +
this.petalCount + ' petals!');
};
var flower = new LateBloomer();
flower.bloom(); // 一秒鐘后, 調用'declare'方法
```
- js應用場景
- js組成
- js書寫位置
- 浮點數精度問題
- undefined與null的區別
- 數據類型轉換
- 運算符優先級
- 代碼調試
- 函數
- 函數的定義和調用
- 函數的return細節
- 函數是一種數據類型
- this的指向
- 函數成員
- 函數閉包
- 作用域
- 預解析
- js對象
- 對象的創建與調用
- new關鍵字
- this關鍵字
- 構造函數創建對象
- 事件
- 數據類型
- 繼承
- 雜項
- 如何阻止標簽的默認行為
- 為一個標簽綁定或移除任何一個事件
- 如何阻止事件的冒泡行為
- 事件的三個階段
- 移動元素的條件
- 勻速動畫函數封裝
- 變速動畫函數封裝
- 獲取元素的css屬性值
- 數據類型判斷方法
- 創建對象的7種寫法
- 如何繼承
- 為js內置對象添加原型函數
- 將局部變量轉換為全局變量
- call函數的用法
- 沙箱
- 淺拷貝
- 深拷貝
- 對象賦值會改變對象
- 解析URL中的字符串
- 格式化日期
- 獲取當前瀏覽器類型
- Vue3.x
- 調式工具Vue Devtools