[TOC]
# 深入淺出 妙用Javascript中apply、call、bind
## apply、call用法的簡單示例
```javascript
function fruits() {}
fruits.prototype = {
color: "red",
say: function() {
console.log("My color is " + this.color);
}
}
var apple = new fruits;
apple.say(); //My color is red
banana = {
color: "yellow"
}
apple.say.call(banana); //My color is yellow
apple.say.apply(banana); //My color is yellow
```
## apply 、 call 區別
注意apply傳遞的參數是數組,而call是按參數順序傳遞
```javascript
var func = function(arg1, arg2) {
};
func.call(this, arg1, arg2);
func.apply(this, [arg1, arg2])
```
## apply 、 call 用法示例
* 數組之間追加
```javascript
var array1 = [12 , "foo" , {name "Joe"} , -2458];
var array2 = ["Doe" , 555 , 100];
Array.prototype.push.apply(array1, array2);
/* array1 值為 [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */
```
* 獲取數組中的最大值和最小值
```javascript
var numbers = [5, 458 , 120 , -215 ];
var maxInNumbers = Math.max.apply(Math, numbers), //458
maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458
```
* 驗證是否是數組(前提是toString()方法沒有被重寫過)
```javascript
functionisArray(obj){
returnObject.prototype.toString.call(obj) === '[object Array]' ;
}
```
* 類(偽)數組使用數組方法
```javascript
var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));
```
## 一道面試題目
```javascript
//使用 log 代理 console.log
function log(msg) {
console.log(msg);
}
log(1);
log(1,2);
//優雅的方法
function log(){
console.log.apply(console, arguments);
};
log(1);
log(1,2);
//添加一個 (app) 前綴
function log(){
var args = Array.prototype.slice.call(arguments);
args.unshift('(app)');
console.log.apply(console, args);
};
```
## bind 用法簡單示例
```javascript
// 正常情況下使用變量保存 this 值
var foo = {
bar : 1,
eventBind: function(){
var _this = this ;
$('.someClass').on('click',function(event) {
/* Act on the event */
console.log(_this.bar); //1
});
}
}
// 使用 bind 進行函數綁定
var foo = {
bar : 1,
eventBind: function(){
$('.someClass').on('click',function(event) {
/* Act on the event */
console.log(this.bar); //1
}.bind(this));
}
}
```
```javascript
varfoo = {
x: 3
}
var bar = function(){
console.log(this.x);
}
bar(); // undefined
var func = bar.bind(foo);
func(); // 3
```
## apply、call、bind 比較
``` javascript
var obj = {
x: 81,
};
var foo = {
getX: function() {
return this.x;
}
}
console.log(foo.getX.bind(obj)()); //81
console.log(foo.getX.call(obj)); //81
console.log(foo.getX.apply(obj)); //81
```
# 總結:
apply 、 call 、bind 三者都是用來改變函數的this對象的指向的;
apply 、 call 、bind 三者第一個參數都是this要指向的對象,也就是想指定的上下文;
apply 、 call 、bind 三者都可以利用后續參數傳參;
bind 是返回對應函數,便于稍后調用;apply 、call 則是立即調用
# 參考
[call-apply-bind](https://www.rithmschool.com/courses/advanced-javascript/call-apply-bind)
[深入淺出 妙用Javascript中apply、call、bind](http://www.admin10000.com/document/6711.html)
- 步入JavaScript的世界
- 二進制運算
- JavaScript 的版本是怎么回事?
- JavaScript和DOM的產生與發展
- DOM事件處理
- js的并行加載與順序執行
- 正則表達式
- 當遇上this時
- Javascript中apply、call、bind
- JavaScript的編譯過程與運行機制
- 執行上下文(Execution Context)
- javascript 作用域
- 分組中的函數表達式
- JS之constructor屬性
- Javascript 按位取反運算符 (~)
- EvenLoop 事件循環
- 異步編程
- JavaScript的九個思維導圖
- JavaScript奇淫技巧
- JavaScript:shim和polyfill
- ===值得關注的庫===
- ==文章==
- JavaScript框架
- Angular 1.x
- 啟動引導過程
- $scope作用域
- $q與promise
- ngRoute 和 ui-router
- 雙向數據綁定
- 規范和性能優化
- 自定義指令
- Angular 事件
- lodash
- Test