Bind、Call、Apply 理解与应用
分类:javascript
1. Bind 函数
作用: 返回一个原函数的拷贝,并拥有指定的 this 值和初始参数。
1.1 Bind函数的理解与使用
1.1.1 创建绑定函数的使用
// 创建全局变量
friends = ['glo_zhao', 'glo_dong', 'glo_sun']
const changInfo = {
name: 'chang',
friends: ['zhao', 'qian', 'sun', 'li'],
getOneFri: function () {
// 返回朋友的随机一位
const index = Math.floor(Math.random() * this.friends.length)
return this.friends.slice(index, index + 1)
}
}
// 函数的测试
console.log(changInfo.getOneFri());
// 返回随机一位chang.friends的值,当前的this指向changInfo
// 创建一个函数
const getRanFri = changInfo.getOneFri;
console.log(getRanFri());
// 返回以为随机的全局变量window.friends的值 , 当前的this执行window
// 创建一个新的角色
const newPerson = {
friends: ['per_liu', 'per_wang']
}
// 创建一个绑定函数
const bindGetRanFir = getRanFri.bind(newPerson)
console.log(bindGetRanFir());
// 返回一个随机的newPerson的朋友
1.1.2 构造函数的绑定
function Point(x, y) {
this.x = x
this.y = y
}
Point.prototype.toString = function () {
return `(${this.x} , ${this.y})`
}
const test = new Point(1, 2)
console.log(test.toString()); // (1 , 2)
const getPoint = Point.bind(null, 3, 4)
const exp = new getPoint()
console.log(exp.toString()); // (3 , 4)
1.2 Bind函数实现原理
if (!Function.prototype.myBind) {
(function () { // 立即执行函数
// const arrayPrototypeSlice = Array.prototype.slice;
Function.prototype.myBind = function (otherThis) {
if (typeof this !== 'function') { // 判断是否是函数调用
throw new TypeError('Function.prototype.myBind - what is trying to be bound is not callable')
}
const _this = this
const args = [...arguments].slice(1)
return function F() {
if (this instanceof F) { // 判断是否是构造函数的绑定
return new _this(...args, ...arguments)
}
return _this.apply(otherThis, args.concat(...arguments))
}
}
})()
}
2. Call函数
作用: call()
方法使用一个指定的 this
值和单独给出的一个或多个参数来调用一个函数。
2.1 Call函数的理解与应用
2.1.1 函数的直接调用
const messsage = 'Hello world'
const point = () => {
// 通过作用域链,this指向window,message指向全局作用域
console.log('message is ', messsage);
}
point.call() // message is Hello world
2.1.2 使用call修改this指向
const obj = {
messsage: 'obj_message'
}
const point = function () {
// 通过作用域链,this指向window,message指向全局作用域
console.log('message is ', this.messsage);
}
point.call(obj) // message is obj_message
2.1.3 通过call函数调用父级构造函数,实现函数的继承
function Father(firstName, lastName) { // 定义一个father构造函数
this.lastName = lastName
this.firstName = firstName
this.getFamilyName = function () {
return `${this.lastName} ${this.firstName}`
}
}
function Child(firstName, father) { // 定义一个child构造函数
Father.call(this, firstName, father.lastName)
this.firstName = firstName // 重定向一下 名字
}
let zhang_Fa = new Father('san', 'zhang')
let zhang_ch = new Child('liang', zhang_Fa)
console.log(zhang_ch.getFamilyName()); // zhang liang
2.2 call函数的实现
if (!Function.prototype.myCall) {
(function () {
Function.prototype.myCall = function (context) {
context = context || window // 获取到函数的变量
context.fn = this // 获取调用者函数
// point.myCall(obj,arg1,arg2,···) => args = [ arg1···] // 获取参数
const args = [...arguments].slice(1)
// point.myCall(obj,arg1,arg2,···) => obj.fn(arg1,arg2,···) // 携带返回值的参数执行
const result = context.fn(...args)
delete context.fn // 删除绑定的函数
return result
}
})()
}
3. Apply函数
作用: apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。
3.1 Apply的实现
apply()
的使用方式与call()
的方式相似,区别在于函数的参数,apply
的参数为数组,call
的参数为参数列表
if (!Function.prototype.myApply) {
(function () {
Function.prototype.myApply = function (context) {
context = context || window
context.fn = this // 函数绑定
let result
if (arguments[1]) { // 如果存在第二个参数的话
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
delete context.fn
return result
// const args = [...argumentsr].slice(1)
}
})()
}