「回顾2022,展望2023,我正在参与2022年终总结征文大赛活动」
1. 前语
对于JavaScript开发者来说,this 不熟悉的小伙伴点这里 是一个让咱们头疼的要害字。但当咱们真的学会this这个机制之后,就觉得它是真的香。下面我就来介绍this显现绑定call()、apply()、bind() 三种办法吧。
2. call() 办法
界说: 调用一个目标的办法,以另一个目标换当时目标,可将一个函数的目标上下文从初始的上下文改动为由thisObj
指定的新目标。
语法: Function.call(thisObj, arg1, arg2, ….)
阐明:
- 如果没供给
thisObj
参数,则会指向大局Window
。 -
call
承受多个参数为Function
的参数,调用后回来Funtion
函数的履行成果。
完成call
要害因素:
- 使Funtion 函数的this指向thisObj。
- 将Funtion 函数履行,一起将后序参数作为funtion的参数,若有回来值则回来。
Function.prototype.my_call = function() {
if (typeof this !== 'function') { // 优化函数才能够调用`call`
throw new TypeError('error')
}
let obj = arguments[0]
const args = Array.prototype.slice.call(arguments, 1) // 第一个函数以外的参数
obj = obj || window // 避免没传第一个参数
const fn = Symbol('fn') // 声明 仅有变量 fn
obj[fn] = this // 改动函数this指向(要害代码)
const result = obj[fn](...args) // 调用函数(要害代码)
delete obj[fn] // 删去 obj 上的 fn 特点
return result // 回来函数履行成果
}
var name = 'zhangsan'
var obj = {
name: 'lisi',
fn: 123
}
//咱们完成
const res = foo.my_call(obj, 1, 2)
console.log(res); // lisi 3
// 官方
const res1 = foo.call(obj, 1, 2) // lisi 3
console.log(res1); // lisi 3
3. apply() 办法
界说: 与call办法相同,但apply第二个参数承受一个数组。
语法: Function.call(thisObj, [arg1, arg2, …])
阐明:
- 如果没供给
thisObj
参数,则会指向大局Window
。 -
apply
第二个参数为数组,调用后回来Funtion
函数的履行成果。
完成apply
要害因素:
- 使Funtion 函数的this指向thisObj。
- 将Funtion 函数履行,一起将第二个参数作为Funtion的参数,回来Function的履行成果。
Function.prototype.my_apply = function(obj, args) {
if (typeof this !== 'function') { // 优化函数才能够调用`apply`
throw new TypeError('error')
}
obj = obj || window // 避免没传第一个参数
const fn = Symbol('fn') // 声明 仅有变量 fn
obj[fn] = this // 改动函数this指向(要害代码)
const res = obj[fn](...args) // 调用函数(要害代码)
delete obj[fn] // 删去 obj 上的 fn 特点
return res // 回来函数履行成果
}
var name = 'zhangsan'
var obj = {
name: 'lisi',
fn: 123
}
//咱们完成
const res = foo.my_apply(obj, [1, 2])
console.log(res); // lisi 3
// 官方
const res1 = foo.aplly(obj, [1, 2]) // lisi 3
console.log(res1) // lisi 3
4. bind() 办法
界说: 与call办法相同, 可承受任意参数。
语法: Function.call(thisObj, arg1, arg2, …)
阐明:
- 如果没供给
thisObj
参数,则会指向大局Window
。 -
bind
承受任意个参数,调用后回来一个新的绑定函数。
完成bind
要害因素:
- 使Funtion 函数的this指向thisObj。
- 将Funtion 函数履行,一起其他参数作为Funtion的参数, 回来一个新的绑定函数。
- 如果 new 了回来的新的绑定的函数,该函数的this需求指向Function函数而不是thisObj。
Function.prototype.my_bind = function(obj) {
if (typeof this !== 'function') { // 优化函数才能够调用`bind`
throw new TypeError('error')
}
obj = obj || window // 避免没传第一个参数
const args = Array.prototype.slice.call(arguments, 1) // 第一个函数以外的参数
const _this = this
const pro = function() {}
if (this.prototype) {
pro.prototype = this.prototype
}
const bound = function () { // 声明一个bound函数
// 判断该函数是否被new
return _this.apply( // 掉用 apply 办法改动 this指向
this instanceof pro ? this : obj, // 判断 bound 函数时候被 new 了 如果 new this 指向foo 反之,指向 obj
args.concat(Array.prototype.slice.call(arguments))
)
}
bound.prototype = new pro() // bound 函数的原型承继到了foo的原型 (原型链承继)
return bound // 回来 bound 函数
}
var name = 'zhangsan'
var obj = {
name: 'lisi',
fn: 123
}
function foo(a, b) {
console.log(this.name, a + b);
return a + b
}
// 自己完成
const bar = foo.my_bind(obj)
console.log(bar());
let bar1 = new bar(3, 4)
console.log(bar1);
// 官方
const bar2 = foo.bind(obj)
console.log(bar2());
let bar3 = new bar(3, 4)
console.log(bar3);
5. 结语
在不同的开发环境下,咱们灵活的运用这三种显现绑定办法,能够使咱们的this永久不会丢失。