
实现call方法
js
Function.prototype.myCall = function (context, ...args) {
if (!context || context === null) {
context = window
}
// 创建唯一的key值,作为我们构造的context内部方法名
let fn = Symbol()
// this指向调用call的函数
context[fn] = this
// 执行函数并返回结果,相当于把自身作为传入的context的方法进行调用了
return context[fn](...args)
}js
// 第一版
Function.prototype.myCall1 = function (context) {
context.fn = this
context.fn()
delete context.fn
}
// 第二版
Function.prototype.myCall2 = function (context) {
context.fn = this
var args = []
for (i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + ']')
}
eval('context.fn(' + args + ')')
delete context.fn
}
// 第三版
Function.prototype.myCall3 = function (context) {
var context = context || window
context.fn = this
var args = []
for (var i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + ']')
}
var result = eval('context.fn(' + args + ')')
delete context.fn
return result
}
// 最终版
Function.prototype.myCall = function (context) {
var context = context || window
context.fn = this
var args = []
for (var i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + ']')
}
var result = eval('context.fn(' + args + ')')
delete context.fn
return result
}
var foo = {
value: 1,
}
function bar(name, age) {
console.log(name)
console.log(age)
console.log(this.value)
}
// bar.myCall1(foo);
bar.myCall2(foo, 'name', 18)
// bar.myCall(foo, 'kevin', 18);js
Function.prototype.myCall = function (context, ...args) {
let ctx = context || window
// 将当前被调用的方法定义在ctx.func上
// 新建一个唯一的Symbol变量避免重复
let func = Symbol()
ctx[func] = this
args = args ? args : []
// 以对象调用形式调用func,此时this指向ctx也就是传入的需要绑定的this指向
const res = args.length > 0 ? ctx[func](...args) : ctx[func]()
// 删除该方法,不然会对传入对象造成污染
delete ctx[func]
return res
}js
// call做了什么
// - 将函数设为对象的属性
// - 执行和删除这个函数
// - 指定this到函数并传入给定参数执行函数
// - 如果不传入参数,默认指向为window
// 模拟call bar.mycall(null)
// 实现一个call方法
// 原理:利用context.xxx = self obj.xx = func --> obj.xx()
Function.prototype.myCall = function (context = window, ...args) {
// this --> func context --> obj args --> 传递过来的参数
// 在context上加一个唯一值不影响context上的属性
let key = Symbol('key')
// context为调用的上下文,this此处为函数,将这个函数作为context的方法
context[key] = this
let result = context[key](...args)
delete context[key]
return result
}
