Function内置的实例方法,call,apply一般是用来改变执行上下文的,比如我们写了一个方法A,在A里面需要写相同的逻辑,这个时候就可以用call,apply来复用这些逻辑。
如下文:我们需要Food里面name的内容,明明直接在Food里面执行this.name=name就好了,但是我们用call去继承了Product的函数内容,这样就不需要重复写一遍了。
工作中,写一些基础类,公共的函数的时候就可以考虑使用他们。
function Product(name, price) { this.name = name this.price = price this.discount = function() { return this.price * 0.9 }} function Food(name, price) { Product.call(this, name, price) this.category = 'food'} const cheese = new Food('cheese', 5)console.log(cheese.discount()) // ✅ 输出: 4.5console.log(cheese.name)
call和apply的共同特点就是:能够改变函数的执行上下文,将一个对象的方法交给另一个对象来执行,而且是立即被调用的。
区别在于:
call:
● 调用call的对象必须是一个函数,Function.call(obj,...args)
● 第一个是一个对象,后续函数的调用者都会指向这个对象,
● 从第二个参数开始,所有的参数都会映射到Function接收到的对象上面,如果传入的是数组的话,那么函数的第一个参数接收的是这个数组,后续都为undefied
function Product(name, price) { this.name = name this.price = price this.discount = function() { return this.price * 0.9 }} function Food(name, price) { Product.call(this, name, price) // 借用 Product 的初始化逻辑 this.category = 'food'} const cheese = new Food('cheese', 5)console.log(cheese.discount()) // ✅ 输出: 4.5console.log(cheese.name) // ✅ 输出: cheese
apply:
● 和call的基本一致,区别在于第二个参数,apply传入的是一个数组或类数组中
function test(a,b,c){ console.log(a,b,c)}Function.prototype.myApply = function (context,arr){ if (context === null || context === undefined) { context = typeof window !== 'undefined' ? window : global } const key = Symbol() context[key] = this const result = context[key](...arr) delete context[key] return result}test.apply(null,[1,2,3]) // 1,2,3test.myApply(null,[1,2,3])
bind:
● 调用apply的对象必须是一个函数,Function.bind(obj,...args)
● call和apply是立即被执行的,而apply不一样,他是返回了一个函数,在被调用的时候才会进行执行。
function myBind(context,...boundArgs){ // 保存原函数 const originalFunction = this // 返回新函数 return function(...callArgs) { // 合并参数:bind 时传入的参数 + 调用时传入的参数 const allArgs = [...boundArgs, ...callArgs] // 使用 apply 执行原函数 return originalFunction.apply(context, allArgs) }}