说多无益, 直接上代码, 肯定还有一些不完善的地方, 我参考了一下
原生js源码之JavaScript的call方法,自己来实现
call()
'use strict'
var person = {
name: "Tom",
sayHi(a, b) {
// console.log('a', a)
// console.log('b', b)
// return this.name + " 在向你问好!" + a + b
return this.name + " 在向你问好!" + a.name + b.name;
}
}
var pig = {
name: 'Jerry'
}
/**
* 只处理了 参数为 string, number, object 的情况
* @returns any
*/
Function.prototype.myCall = function() {
if (arguments.length === 0) {
return this()
} else {
// 第一个参数作为上下文
let context = arguments[0]
// 这两行判断写不写都行其实, 严格模式下不管怎样都会报错的
if (context === null || context === undefined) return this()
if (typeof context !== 'object') context = {}
// this 是传入进来的函数, this.name 是函数名, 给传进来的 context 添加方法
context[this.name] = this
let func = this.name + '('
let arg
let myArgs = []
for (let i = 1; i < arguments.length; i++) {
arg = arguments[i]
console.log('arg', arg)
if (typeof arg === 'string') {
if (i === 1) {
func += `'${arg}'`
} else {
func += `,'${arg}'`
}
} else if (typeof arg === 'number') {
if (i === 1) {
func += arg
} else {
func += "," + arg
}
} else if (typeof arg === 'object') {
myArgs.push(arg)
if (i === 1) {
func += `myArgs[${i - 1}]`
} else {
func += `,myArgs[${i - 1}]`
}
}
}
func += ')'
console.dir(func)
// 拿到执行后的结果
const result = eval('context.'+ func)
// 删除新增的属性
delete context[this.name]
// 返回执行后的结果
return result
}
}
// console.log(person.sayHi.myCall(pig, 1, 2))
console.log(person.sayHi.myCall(pig, { name: 'c' }, { name: 'd' }))
console.log(pig)
apply()
其实和 call() 没区别, 只是换了一下参数传入的形式
'use strict'
var person = {
name: "Tom",
sayHi(a, b) {
// console.log('a', a)
// console.log('b', b)
return this.name + " 在向你问好!" + a + b
// return this.name + " 在向你问好!" + a.name + b.name;
}
}
var pig = {
name: 'Jerry'
}
/**
* 只处理了 参数为 string, number, object 的情况
* @returns any
*/
Function.prototype.myApply = function() {
if (arguments.length === 0) {
return this()
} else {
// 第一个参数作为上下文
let context = arguments[0]
// 这两行判断写不写都行其实, 严格模式下不管怎样都会报错的
if (context === null || context === undefined) return this()
if (typeof context !== 'object') context = {}
// this 是传入进来的函数, this.name 是函数名, 给传进来的 context 添加方法
context[this.name] = this
let func = this.name + '('
let arg
let myArgs = []
for (let i = 0; i < arguments.length; i++) {
arg = arguments[1][i]
console.log('arg', arg)
if (typeof arg === 'string') {
if (i === 0) {
func += `'${arg}'`
} else {
func += `,'${arg}'`
}
} else if (typeof arg === 'number') {
if (i === 0) {
func += arg
} else {
func += "," + arg
}
} else if (typeof arg === 'object') {
myArgs.push(arg)
if (i === 0) {
func += `myArgs[${i}]`
} else {
func += `,myArgs[${i}]`
}
}
}
func += ')'
console.dir(func)
// 拿到执行后的结果
const result = eval('context.'+ func)
// 删除新增的属性
delete context[this.name]
// 返回执行后的结果
return result
}
}
console.log(person.sayHi.myApply(pig, [1, 2]))
// console.log(person.sayHi.myApply(pig, [{ name: 'c' }, { name: 'd' }]))
console.log(pig)
bind()
只是需要返回一个函数了
'use strict'
var person = {
name: "Tom",
sayHi(a, b) {
// console.log('a', a)
// console.log('b', b)
// return this.name + " 在向你问好!" + a + b
return this.name + " 在向你问好!" + a.name + b.name;
}
}
var pig = {
name: 'Jerry'
}
/**
* 只处理了 参数为 string, number, object 的情况
* @returns any
*/
Function.prototype.myBind = function() {
if (arguments.length === 0) {
return this
} else {
let context = arguments[0]
// 这两行判断写不写都行其实, 严格模式下不管怎样都会报错的
if (context === null || context === undefined) return this()
if (typeof context !== 'object') context = {}
context[this.name] = this
const that = this
return function() {
let arg
let func = that.name + '('
let myArgs = []
for (let i = 0; i < arguments.length; i++) {
arg = arguments[i]
if (typeof arg === 'string') {
if (i === 0) {
func += `'${arg}'`
} else {
func += `,'${arg}'`
}
} else if (typeof arg === 'number') {
if (i === 0) {
func += arg
} else {
func += "," + arg
}
} else if (typeof arg === 'object') {
myArgs.push(arg)
if (i === 0) {
func += `myArgs[${i}]`
} else {
func += `,myArgs[${i}]`
}
}
}
func += ')'
console.dir(func)
const result = eval('context.' + func)
delete context[that.name]
return result
}
}
}
console.log(person.sayHi.myBind(pig)({ name: 'c' }, { name: 'd' }))
// console.log(person.sayHi())