Call()、Apply()、Bind()用法及简单手写实现

call()

call() 方法可以是对象重用其他对象上的方法,此方法是JS预定义的,可以用来调用所有者对象作为参数的方法

用法示例:

const fully = {
    fullName: function() {
        return this.firstName + " " + this.lastName;
    }
}
const p = {
    firstName:"Jhon",
    lastName: "Park",
}
fully.fullName.call(p);  // 返回 "Jhon Park"

接收参数:

const fully = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + "," + city + "," + country;
  }
}
const p = {
  firstName:"Jhon",
  lastName: "Park"
}
fully.fullName.call(p, "La", "USA"); // 返回 "Jhon Park,La,USA"

手写实现:

/**
 * 当第一个参数为null/undefined,this指向全局对象window,
 * 若值为原始值则指向该原始值的自动包装对象,如 String、Number、Boolean
 * 为了避免函数名与上下文(ctx)的属性发生冲突,使用Symbol类型作为唯一值
 * 将函数作为传入的上下文(ctx)属性执行
 * 函数执行完成后删除该属性
 * 返回执行结果
 * */
const person = {
	firstName: 'Jhon',
	lastName: 'Park'
}

const fully = {
	fullName: function(){
		return this.firstName + ' ' + this.lastName
	}
}

Function.prototype.newCall = function(context,...args){
    let cxt = context || window;
    //新建一个唯一的Symbol变量避免重复
    let fn = Symbol() 
	// cxt[fn]定义当前被调用的方法,绑定this以便用对象形式调用
    cxt[fn] = this;
	
    args = args ? args : []
    //以对象调用形式调用fn,此时this指向cxt 也就是传入的需要绑定的this指向
    const res = args.length > 0 ? cxt[fn](...args) : cxt[fn]();
    //删除该方法,不然会对传入对象造成污染
    delete cxt[fn];
    return res;
}

const result1 = fully.fullName.newCall(person)
console.log('Call:', result1);

apply()

与call()方法非常相似,apply() 方法可以是对象重用其他对象上的方法,此方法是JS预定义的,可以用来调用所有者对象作为参数的方法

用法示例:

const fully = {
    fullName: function() {
        return this.firstName + " " + this.lastName;
    }
}
const p = {
    firstName:"Jhon",
    lastName: "Park",
}
fully.fullName.apply(p);  // 返回 "Jhon Park"

接收参数:

const fully = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + "," + city + "," + country;
  }
}
const p = {
  firstName:"Jhon",
  lastName: "Park"
}
fully.fullName.apply(p, ["La", "USA"]); // 返回 "Jhon Park,La,USA"

手写实现:

const fully = {
    fullName: function() {
        return this.firstName + " " + this.lastName;
    }
}
const person2 = {
	firstName: 'Anna',
	lastName: 'Wang'
}
Function.prototype.newApply = function(context,args = []){
    let cxt = context || window; 
    let func = Symbol()
    cxt[func] = this;
    
    const res = args.length > 0 ? cxt[func](...args) : cxt[func]();
    delete cxt[func];
    return res;
}
const result2 = fully.fullName.newApply(person2)
console.log('Apply:', result2); // Apply: Anna Wang

call() 与 apply():

call 与 apply 的相同点:

方法的含义是一样的,即方法功能是一样的;
第一个参数的作用是一样的;
call 与 apply 的不同点:两者传入的列表形式不一样

call可以传入多个参数;
apply只能传入两个参数,所以其第二个参数往往是作为数组形式传入

如果要使用数组而不是参数列表,则 apply() 方法非常方便。

bind()

bind()方法主要就是将函数绑定到某个对象,bind()会创建一个函数,函数体内的this对象的值会被绑定到传入bind()第一个参数的值,bind() 除了 this 外,还可传入多个参数,创建的新函数可能传入多个参数,新函数可能被当做构造函数调用,函数可能有返回值。

用法示例:

const fully = {
    fullName: function() {
        return this.firstName + " " + this.lastName;
    }
}
const p = {
    firstName:"Jhon",
    lastName: "Park",
}
fully.fullName.bind(p)();  // 返回 "Jhon Park"

接收参数:

const fully = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + "," + city + "," + country;
  }
}
const p = {
  firstName:"Jhon",
  lastName: "Park"
}
fully.fullName.bind(p)("La", "USA"); // 返回 "Jhon Park,La,USA"

手写实现:

const fully = {
    fullName: function() {
        return this.firstName + " " + this.lastName;
    }
}
const person3 = {
	firstName: 'Kay',
	lastName: 'Sun'
}
Function.prototype.newBind = function (context, ...args) {
    //新建一个变量赋值为this,表示当前函数
    const fn = this
    //判断有没有传参进来,若为空则赋值[]
    args = args ? args : []
    //返回一个newFn函数,在里面调用fn
    return function newFn(...newArgs) {
        if (this instanceof newFn) {
            return new fn(...args, ...newArgs)
        }
        return fn.apply(context, [...args,...newArgs])
    }
}
const result3 = fully.fullName.newBind(person3)()
console.log('Bind:', result3); // 返回 Bind: Kay Sun
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值