[TOC]
* * * * *
## 一 . Function.prototype.call
> call() 方法調用一個函數, 其具有一個指定的this值和分別地提供的參數(參數的列表)。
>[info]語法:
~~~
fun.call(thisArg, arg1, arg2, ...)
參數:
thisArg
在fun函數運行時指定的this值。
PS:需要注意的是,指定的 this 值并不一定是該函數執行時真正的 this值。
1.如果這個函數處于非嚴格模式下,則指定為 null 和 undefined 的 this 值會自動指向全局對象( 瀏覽器中就是 window 對象 );
2.同時值為原始值(數字,字符串,布爾值)的 this 會指向該原始值的自動包裝對象。
arg1, arg2, ...
指定的參數列表。
~~~
>[info] 用法 1:模擬面向對象的繼承
~~~
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
/*
這一句相當于:
1.把 Product 函數里的this指向當前函數的環境對象;
2.執行Product函數
等價于,給函數增添了一段代碼:
this.name = name;
this.price = price;
*/
this.category = 'food';
}
console.log(new Food('cheese', 5).name);
//輸出 'cheese'
~~~
>[info]用法 2:為了避免 for循環語句定義的變量,避免因閉包特性而出錯
~~~
var person= [
{sex: 'man', name: 'wdd'},
{sex: 'woman', name: 'girl'}];
for (var i = 0; i < person.length; i++) {
(function (i) {
this.print = function () {
console.log('My index is',i);
}
}).call(person[i], i);
}
這個函數給原數組的每個元素(為對象),添加了一個 print 方法
~~~
* * * * *
## 二. Function.prototype.apply
>注意:該方法與 call 只有一個區別,就是 call() 方法接受的是若干個參數的列表,而 apply() 方法接受的是一個包含多個參數的數組。
>[info] 用法 1:求出一組數中的最大和最小值
~~~
用傳統的方法:
var numbers = [5, 6, 2, 3, 7];
var max = -Infinity, min = +Infinity;
for (var i = 0; i < numbers.length; i++) {
if (numbers[i] > max)
max = numbers[i];
if (numbers[i] < min)
min = numbers[i];
}
利用 apply 借用 Math 的方法:
Math.max/min(arg1,arg2,arg3,...)
var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);
~~~
* * * * *
## 三. Function.prototype.bind
>`bind()` 方法創建一個新的函數, 當被調用時,將其 this 關鍵字設置為提供的值,在調用新函數時,在任何提供之前提供一個給定的參數序列。
>[danger] PS:這個方法很大一個功能就是綁定執行環境對象,但是和 call & apply 方法的用法還是很不同的。
>[info]語法:
~~~
fun.bind(thisArg, [arg1,arg2,...])
參數:
thisArg
當綁定函數被調用時,該參數會作為原函數運行時的 this 指向。
當使用new 操作符調用綁定函數時,該參數無效。
arg1, arg2, ...
當綁定函數被調用時,這些參數將置于實參之前傳遞給被綁定的方法。
返回值
返回由指定的this值和初始化參數改造的原函數拷貝
~~~
>[info]用法1(綁定執行環境對象):
~~~
this.x = 9;
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX();
/*
返回 81
用對象調用這個方法,則函數的執行環境對象就是這個調用對象,即 this 指向這個調用對象
*/
var retrieveX = module.getX;
retrieveX();
/*
返回 9
在這種情況下,this 指向全局作用域
調用這個函數的環境對象是全局作用域
*/
var boundGetX = module.getX.bind(module);
/*
構造了一個新函數,這個函數里的 this 固定指向 module
*/
boundGetX();
// 返回 81
~~~
>[info]用法二:偏函數(Partial Functions)
> `bind()` 的另一個最簡單的用法是使一個函數擁有預設的初始參數。這些參數(如果有的話)作為 `bind()` 的第二個參數跟在 `this`(或其他對象)后面。之后它們會被插入到目標函數的參數列表的開始位置,傳遞給綁定函數的參數會跟在它們的后面。
~~~
function list() {
return Array.prototype.slice.call(arguments);
}
var list1 = list(1, 2, 3);
// [1, 2, 3]
// Create a function with a preset leading argument
var leadingThirtysevenList = list.bind(undefined, 37);
var list2 = leadingThirtysevenList();
// [37]
var list3 = leadingThirtysevenList(1, 2, 3);
// [37, 1, 2, 3]
~~~
>[info]用法三:快捷調用
>在你想要為一個需要特定的 this 值的函數創建一個捷徑(shortcut)的時候,bind() 方法也很好用。
你可以用 Array.prototype.slice 來將一個類似于數組的對象(array-like object)轉換成一個真正的數組,就拿它來舉例子吧。
你可以創建這樣一個捷徑:
~~~
var slice = Array.prototype.slice;
/*
數組以及字符串類型下的一些內置函數,
都是需要調用它們的執行環境對象的,
那么這里綁定的對象就被用作執行環境對象。
*/
slice.apply(arguments);
用 bind() 可以使這個過程變得簡單。
在下面這段代碼里面,
slice 是 Function.prototype的 apply() 方法的綁定函數,
并且將 Array.prototype 的 slice() 方法作為 this 的值。
這意味著我們壓根兒用不著上面那個 apply() 調用了。
var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.apply.bind(unboundSlice);
slice(arguments);
~~~