JS面試中你不知道的call apply bind方法及使用場景詳解
面試
面試官 :說一下 call apply bind 的三者區(qū)別吧?
我:啊.....這。
三者區(qū)別
call
我們先來看看 call call 函數接收兩個參數
@params1 需要指向this
@params2 需要攜帶的參數
就拿這段代碼 來說 我調用 foo 函數 的時候 想去 執(zhí)行obj 中的 eat函數 怎么辦?
默認 我的 foo 里面什么頁面有 怎么可能會打印 吃飯呢?this默認指向 window ,window 對象中 沒有 eat 方法不應該 報錯 not defind 嗎?
let obj = {
eat: function (args) {
console.log("吃飯", args);
}
}
function foo(...args) {
this.eat(args)
}
你可以這樣 , 此時調用的時候 foo 的函數 this 就指向了 obj 但是只是這一次調用哦 ,下次 this 是指向 window 的
console.log(foo.call(obj, 123, 456)); / / 吃飯 [ 123, 456 ]
調用結果 : 傳入 this 和 參數 立即執(zhí)行函數
apply.
@params1 需要指向this
@params2 需要攜帶的參數 傳入的參數數據類型為 Array
let obj = {
eat: function (args) {
console.log("吃飯", args);
}
}
function foo(...args) {
this.eat(args)
}
console.log(foo.apply(obj, [1, 2, 3])); // 吃飯 [1,2,3 ]
調用結果 : 傳入 this 和 參數,立即執(zhí)行
bind
@params1 需要指向this
@params2 需要攜帶的參數
let obj = {
eat: function (args) {
console.log("吃飯", args);
}
}
function foo(...args) {
this.eat(args)
}
console.log(foo.bind(obj, 1, 2, 3)()); //吃飯 [ 1, 2, 3 ]
調用結果 : 傳入 this 和 參數 返回一個 新的函數,不會立即執(zhí)行
總結
call 函數 傳入綁定 this的對象 ,攜第二個參數以 參數列表形式傳入 并會立即執(zhí)行
apply 函數 傳入綁定 this的對象 第二個參數以 數組的形式 傳入 并會立即執(zhí)行
bind 函數 傳入綁定 this的對象 第二個參數以 數組或參數列表的形式傳入 不會立即執(zhí)行函數會返回一個新的函數 自由調用
應用場景
利用call 實現 構造函數原型繼承
function Person(name, age, friends) {
this.friends = friends
this.name = name
this.age = age
}
Person.prototype.eat = function () {
console.log(`${this.name}在吃飯`);
}
Person.prototype.running = function () {
console.log(`${this.name}去跑步了`);
}
function Student(study, name, age, friedns) {
Person.call(this, name, age, friedns)
this.study = study
}
function Teacher(plaseLoveStudent) {
this.plaseLoveStudent = plaseLoveStudent
}
//繼承 person
Student.prototype = new Person()
const stu = new Student('語文', "張三", 18, ['王安石'])
const stu2 = new Student('數學', "李四", 18, ['哈利波特'])
const tec = new Teacher("王安怡")
console.log(stu === stu2);
console.log(stu);
console.log(stu.friends);
console.log(stu2.friends);
簡單實現
call
實現思路 :
1:在Function 原型身上添加一個方法。
2:mycall 接受 兩個參數 一個是綁定的 this,還有就是 參數列表
3:保存調用者,其實這里更嚴謹一點還需要判斷調用者的 類型
4:判斷傳入的thisArgs 是不是 undefined 或者 null 如果是 則 this指向 window 否則將 綁定的 this封裝成 一個對象
5:然后將 函數本身保存在 上面封裝好的對象中
6:調用并傳入args
7:完成實現 this指向的改變
Function.prototype.mycall = function (thisArgs, ...args) {
/**
*
* 保存this(當前調用者)
*
*/
const newFunc = this
// 在當前調用者 this身上 保存 調用者
thisArgs = (thisArgs !== undefined && thisArgs !== null) ? Object(thisArgs) : window
thisArgs.func = newFunc
thisArgs.func(...args)
}
apply
apply 就不說了 實現思路是一樣的 只不過傳入的參數不一樣做一個判斷就行了
Function.prototype.myapply = function (thisArgs, argArray) {
if (!(argArray instanceof Array)) {
throw '參數類型限定為 Array'
}
else {
const func = this
thisArgs = (thisArgs !== undefined && thisArgs !== null) ? Object(thisArgs) : window
thisArgs.fn = func
thisArgs.fn(argArray)
}
}
bind
bind 跟 apply call 有一些區(qū)別
bind 會返回一個新的函數 , 所以我們在內部需要自己定義一個 函數 給返回出去, 并且,可能出現 返回新函數調用時 繼續(xù)傳入參數 所以我們需要將參數合并
Function.prototype.mybind = function (thisArgs, ...argArray) {
const oldFunc = this
console.log(this);
thisArgs = (thisArgs !== undefined && thisArgs !== null) ? Object(thisArgs) : window
function proxyFn(...args) {
thisArgs.func = oldFunc
const funcCallResult = thisArgs.func([...argArray, ...args]) // 合并兩次的 參數
delete thisArgs.func
return funcCallResult
}
return proxyFn
}
謝謝,到此就完成了簡單版的 call apply bind 的實現,更多關于JS call apply bind方法的資料請關注腳本之家其它相關文章!
相關文章
微信小程序獲取循環(huán)元素id以及wx.login登錄操作
這篇文章主要介紹了微信小程序獲取循環(huán)元素id以及wx.login登錄操作的相關資料,這里提供實例幫助大家實現該功能,需要的朋友可以參考下2017-08-08

