写在前面
如果本文对您有所帮助,就请点个关注吧!
获取当前环境的公共方法
let getEnv = function() {
return this
}
一、手写call方法
1. 源码
Function.prototype.myCall = function (ctx, ...args) {
// 设置默认的this
ctx = arguments[0] || getEnv()
// 若传入的对象是字符串,需要装箱
if (ctx instanceof String) {
ctx = new String(ctx)
}
// 声明一个独有的Symbol属性,防止覆盖
const fun = Symbol('fun')
// 为传入对象设置函数
ctx[fun] = this
// 执行函数并返回结果
const result = ctx[fun](...args)
// 删除我们设置的属性
delete ctx[fun]
// 返回结果
return result
}
2. 测试
let person = {
name: 'person1',
say() {
return this.name
}
}
let person2 = {
name: 'person2'
}
let res = person.say.myCall(person2)
console.log(res)
// 测试结果
// person2
二、手写apply方法
1. 源码
Function.prototype.myApply = function (ctx, args) {
// 设置默认的this
ctx = arguments[0] || getEnv()
// 若传入的对象是字符串,需要装箱
if (ctx instanceof String) {
ctx = new String(ctx)
}
// 声明一个独有的Symbol属性,防止覆盖
const fun = Symbol('fun')
// 为传入对象设置函数
ctx[fun] = this
// 执行函数并返回结果
let result
if (args) {
result = ctx[fun](...args)
} else {
result = ctx[fun]()
}
// 删除我们设置的属性
delete ctx[fun]
// 返回结果
return result
}
2. 测试
let person = {
name: 'person1',
say(arg1, arg2) {
return this.name + ' ' + arg1 + ' ' + arg2
}
}
let person2 = {
name: 'person2'
}
let res = person.say.myApply(person2, [78, 89])
console.log(res)
// 测试结果
// person2 78 89
三、手写bind方法
1. 源码
Function.prototype.myBind = function (ctx, ...args) {
// 设置默认的this
ctx = arguments[0] || getEnv()
// 记录当前this
const _this = this
// 返回一个函数
return function (...args2) {
// 声明一个独有的Symbol属性,防止覆盖
const fun = Symbol('fun')
// 为传入对象设置函数
ctx[fun] = _this
// 执行函数并记录结果
let result = args.length !== 0 ? ctx[fun](...args) : ctx[fun](...args2)
// 删除我们设置的属性
delete ctx[fun]
// 返回调用结果
return result
}
}
2. 测试
let person = {
name: 'person1',
say(arg1, arg2) {
return this.name + ' ' + arg1 + ' ' + arg2
}
}
let person2 = {
name: 'person2'
}
let res1 = person.say.myBind(person2, 77, 78)()
let res2 = person.say.myBind(person2)(77, 78)
console.log(res1, res2)
// 执行结果
// person2 77 78 person2 77 78
网友评论