wordpress 菜單 標(biāo)簽科學(xué)新概念seo外鏈平臺
Function.prototype.call(thisArg [, arg1, arg2, …])
call() 簡述
- call() 方法 調(diào)用一個函數(shù), 其具有一個指定的 this 值和分別地提供的參數(shù)(參數(shù)的列表)。
- 當(dāng)?shù)谝粋€參數(shù)為 null、undefined 的時候, 默認(rèn) this 上下文指向window。
call() 簡單實(shí)例
const name = 'qianyin';
const product = {name: 'linheng',
};function log(...args){console.log(this.name, ...args);
}log(1, 2, 3); // qianyin 1 2 3
log.call(null, 1, 2, 3); // qianyin 1 2 3
log.call(product, 1, 2, 3); // linheng 1 2 3
call() 對箭頭函數(shù)無效
const name = 'qianyin';
const product = {name: 'linheng',
};const log = (...args) => {console.log(this.name, ...args);
}log(1, 2, 3); // qianyin 1 2 3
log.call(null, 1, 2, 3); // qianyin 1 2 3
log.call(product, 1, 2, 3); // qianyin 1 2 3
補(bǔ)充:
-
箭頭函數(shù)作為函數(shù)的一種形式, 對于this的處理和普通函數(shù)有所區(qū)別, 其沒有自己的 this 上下文,也就是說通過 bind/call/apply 函數(shù)方法設(shè)置 this 值時無效的,會被忽略;
-
因?yàn)榧^函數(shù)沒有自己的 this 上下文, 所以箭頭函數(shù)的 this 上下文等于定義函數(shù)處的this上下文,也就是最近的一個 this 上下文;
-
你可以認(rèn)為箭頭函數(shù)的 this 和調(diào)用者無關(guān),只和其定義時所在的 this 上下文相關(guān);
-
如下代碼: 在對象 obj 中使用箭頭函數(shù)定義 log 函數(shù), 那么因?yàn)榧^函數(shù)沒有自己的 this 上下文, 所以 log 函數(shù)的 this 上下文等于定義箭頭函數(shù)處的 this 上下文, 等于 對象 obj 所處的 this 上下文(window)
const name = 'linheng';
const obj = {name: 'qianyin',log: () => {console.log(this.name);}
};
obj.log(); // linheng
- 那么如果我一定要在 obj 中定義一個 log 函數(shù)并且使得 this 指向?qū)ο?obj 呢?
- 方法一: 使用 function 定義函數(shù)
const name = 'linheng';
const obj = {name: 'qianyin',log: function(){console.log(this.name);}
};
obj.log(); // qianyin
- 方法二: 多此一舉, 在函數(shù) log 中聲明箭頭函數(shù)并調(diào)用, 那么箭頭函數(shù)的 this 上下文等于定義箭頭函數(shù)處的 this 上下文, 等于 log 函數(shù)的上下文(對象 obj )
const name = 'linheng';
const obj = {name: 'qianyin',log: function(){(() => {console.log(this.name);})();},
};
obj.log(); // qianyin
Function.prototype.apply(thisArg [, Array])
Apply() 簡述
- apply() 方法 調(diào)用 一個具有給定 this 值的函數(shù),以及作為一個 數(shù)組(或類似數(shù)組對象) 提供的參數(shù)
- call() 方法的作用和 apply() 方法類似,區(qū)別就是除第一參數(shù) call() 方法接受的是 參數(shù)列表 ,而apply()方法接受的是一個參數(shù) 數(shù)組(或類數(shù)組)。
Apply() 簡單實(shí)例
const name = 'qianyin';
const product = {name: 'linheng',
};function log(...args){console.log(this.name, ...args);
}log([1, 2, 3]); // qianyin [1 2 3]
log.apply(null, [1, 2, 3]); // qianyin 1 2 3
log.apply(product, [1, 2, 3]); // linheng 1 2 3
Apply() 對箭頭函數(shù)無效
const name = 'qianyin';
const product = {name: 'linheng',
};const log = (...args) => {console.log(this.name, ...args);
}log([1, 2, 3]); // qianyin [1 2 3]
log.apply(null, [1, 2, 3]); // qianyin 1 2 3
log.apply(product, [1, 2, 3]); // qianyin 1 2 3
Function.prototype.bind(thisArg [, arg1, arg2, …])
bind() 簡述
- bind() 方法 創(chuàng)建(拷貝)一個新的函數(shù) , 當(dāng)這個新函數(shù)被調(diào)用時 this 指向 thisArg,其 參數(shù)列表前幾項(xiàng)值 為創(chuàng)建時指定的 參數(shù)序列。
- thisArg: 綁定函數(shù)被調(diào)用時,該參數(shù)會作為原函數(shù)運(yùn)行時的 this 指向。當(dāng)使用 new 操作符調(diào)用綁定函數(shù)時,該參數(shù)無效。
bind() 綁定 this 上下文
- bind() 最簡單的用法是創(chuàng)建一個函數(shù),使這個函數(shù)不論怎么調(diào)用都有同樣的 this 上下文。
- JavaScript 新手經(jīng)常犯的一個錯誤是將一個方法從對象中拿出來,然后再調(diào)用,卻又希望方法中的 this 是原來的對象(比如在回調(diào)中傳入這個方法)。
- 如果不做特殊處理的話,一般會丟失原來的對象。從原來的函數(shù)和原來的對象創(chuàng)建一個綁定函數(shù),則能很漂亮地解決這個問題:
- 如果只是單純綁定 this 上下文, 完全可以使用箭頭函數(shù)進(jìn)行替代
// 例一
this.x = 9;var module = {x: 81,getX: function() { return this.x; }
};
module.getX(); // 返回 81 (通過對象調(diào)用函數(shù), 上下文為該對象)
var retrieveX = module.getX; // 獲取對象中函數(shù)的引用地址
retrieveX(); // 返回 9, 在這種情況下, "this" 指向全局作用域(在全局對象下調(diào)用函數(shù))
// 永久為函數(shù) boundGetX 綁定 this 上下文
var boundGetX = retrieveX.bind(module);
boundGetX(); // 返回 81 (函數(shù) this 上下文永久綁定為 module)
// 例二為回調(diào)函數(shù)綁定 this 上下文
var x = 10;
var obj = {x: 20,get: ffunction(){console.log(this.x);}
};
// 將對象中方法取出(函數(shù)的引用地址),作為回調(diào)函數(shù), 又因?yàn)?setTimeout 回調(diào)函數(shù)執(zhí)行的上下文是 window
setTimeout(obj.get, 1000); // 打印 10
// 將對象中方法取出(函數(shù)的引用地址),作為回調(diào)函數(shù)并綁定 this 上下文
setTimeout(obj.get.bind(obj), 1000); // 打印 20
為函數(shù)永久綁定固定參數(shù)
- bind() 的另一個最簡單的用法是使一個函數(shù) 擁有預(yù)設(shè)的初始參數(shù) 。
- 這些參數(shù)(如果有的話)作為bind()的第二個參數(shù)跟在 this(或其他對象)后面。
- 之后它們會 被插入到目標(biāo)函數(shù)的參數(shù)列表的開始位置 ,傳遞給綁定函數(shù)的參數(shù)會跟在它們的后面。
function list() {return Array.prototype.slice.call(arguments);
}var list1 = list(1, 2, 3); // [1, 2, 3]// 為拷貝 list 方法并綁定初始參數(shù)
var leadingThirtysevenList = list.bind(undefined, 37);var list2 = leadingThirtysevenList(); // [37]
var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]
總結(jié)
- 當(dāng)我們使用一個函數(shù)需要改變 this 指向的時候才會用到 call() apply() bind() 當(dāng)然也別忘記了箭頭函數(shù)
- call() 和 apply() 是對函數(shù)的調(diào)用,在調(diào)用的同時綁定 this 上下文并傳遞參數(shù)列表
- bind() 是對函數(shù)的拷貝進(jìn)一步的封裝, 為函數(shù)永久綁定 this 上下文并賦予固定參數(shù)
- call() 和 bind() 以參數(shù)列表形式給函數(shù)指定參數(shù), apply() 則以數(shù)組的形式給函數(shù)指定參數(shù)
apply call bind 的一些運(yùn)用
類數(shù)組轉(zhuǎn)為數(shù)組
- 方法一:
const obj = {0: 'q', 1: 'i', 2: 'q', 3: 'a', 4:'n', 5: 'y', 6:'i', 7:'n', length: 8};const arr = [];Array.prototype.push.apply(arr, obj);console.log(arr); // ["q", "i", "q", "a", "n", "y", "i", "n"]
- 方法二:
const obj = {0: 'q', 1: 'i', length: 2};const arr = Array.prototype.slice.call(obj); // [q, i]
為偽數(shù)組添加新的元素
- 方法一: 當(dāng)然你也可以使用 apply
const obj = {0: 'q', length: 1};Array.prototype.push.call(obj, 'i', 'a', 'n');console.log(obj); // {0: 'q', 1: 'i', 2: 'a', 3: 'n'}
- 方法二:
const obj = {0: 'q', length: 1};const push = Array.prototype.push.bind(obj);push('i', 'a', 'n');console.log(obj); // {0: 'q', 1: 'i', 2: 'a', 3: 'n'}
求數(shù)組中最大值(最小值一樣做法)
const arr = [1,2,3,4,5,6];
const max = Math.max.apply(null, arr);
// 或 const max = Math.max.call(null, ...arr)
console.log(max); // 6
數(shù)組合并追加
const arr = [1, 2];
const brr = [3, 4];
Array.prototype.push.apply(arr, brr);
// 或者 Array.prototype.push.call(arr, ...brr);
// 當(dāng)然還可以這樣 arr.push(...brr);
console.log(arr);
使用 log 代理 console.log
function log(...args){// 在可以通過配置, 或者判斷當(dāng)前開發(fā)環(huán)境來控制是否需要在控制臺打印輸出if(true){console.log.apply(console, args);}
}