call,apply 和 bind用法区别以及手写js函数原生实现call,apply 和 bind

call、apply和bind用法

概念

1、call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数
2、apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。

function getName(name) {
	console.log('name', this.name)
}

var obj = {
	a: 1,
	name: 'aaa'
}

obj调用getName方法,getName中的this指向obj

getName.call(obj) // name aaa

以apply为例
第一个参数为thisArg,调用时采用传入的thisArg代替函数体中this的指向
第二个参数 为一个数组(也可以是类数组arguments),函数会用数组的值取代“参数列表”

apply的调用方式,除了替换函数体中this的指向之外,函数的其他逻辑没有发生任何变化,‘借用’的函数的效果,就跟对象自己拥有这个函数一样

apply:如果第一个传入的参数是null,那么,在函数体中的this会指向全局对象,在浏览器中就是window

call和apply的区别 和bind的区别

1、 call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组
call和apply方式的差别主要体现在传入的形式参数不一样
2、bind的返回值是函数,参数是bind中参数的基础上再往后排
function.bind(thisArg[, arg1[, arg2[, …]]])

手写js函数原生实现call,apply 和 bind

测试用例

	var obj = {
	    name: 'obj'
	}

	function test(...rest) {
	    console.log(this.name)
	    console.log(rest)
	    return rest[0]
	}

原生实现call

纯ES5 实现call

// 纯ES5 实现call
	Function.prototype.myCall = function(obj) {
	    obj = (typeof obj === 'object') ? obj : window
	    var args = []
	    for(let i = 1, len = arguments.length; i<len; i++) {
	        args.push('arguments['+i+']')
	    }
	    obj._fn = this
	    var res = eval('obj._fn('+ args +')')
	    obj._fn = undefined
	    return res
	}

ES6实现call

	Function.prototype.myCall = function(obj, ...rest) {
	    obj = (typeof obj === 'object') ? obj : window
	    // 防止覆盖掉原有属性
	    var _fn = Symbol()
	    obj[_fn] = this
	    var res = obj[_fn](...rest)
	    delete obj[_fn]
	    return res
	}

调用测试用例

	test.myCall(obj, 1, 2, 3) // 'name'为obj

原生实现apply

纯ES5 实现apply

	Function.prototype.myApply = function(obj, arr) {
	    obj = (typeof obj === 'object') ? obj : window
	    var args = []
	    for(let i = 0, len = arr.length; i<len; i++) {
	        args.push('arr['+i+']')
	    }
	    obj._fn = this
	    var res = eval('obj._fn('+ args +')')
	    obj._fn = undefined
	    return res
	}

ES6实现apply

	Function.prototype.myApply = function(obj, arr) {
	    obj = (typeof obj === 'object') ? obj : window
	    var _fn = Symbol()
	    obj[_fn] = this
	    var res 
	    if (!arr) {
	        res = obj[_fn]()
	    } else {
	        res = obj[_fn](...arr)
	    }
	    delete obj[_fn]
	    return res
	}

原生实现bind

纯ES5 实现bind

	Function.prototype.myBind = function(obj) {
	    obj = (typeof obj === 'object') ? obj : window
	    var _this = this
	    var args = []
	    var argArr = []
	    for(let i = 1, len = arguments.length; i<len; i++) {
	        args.push(arguments[i])
	        argArr.push('args['+(i-1)+']')
	    }
	    return function() {
	        for(let i = 0, len = arguments.length; i<len; i++) {
	            argArr.push('arguments['+i+']')
	        }
	        obj._fn = _this
	        const val = eval('obj._fn('+ argArr +')')
	        delete obj._fn
	        return val
	    } 
	}

ES6实现bind

	Function.prototype.myBind = function(obj, ...arg1) {
	    obj = (typeof obj === 'object') ? obj : window
	    var _this = this
	    return function(...arg2) {
	        obj._fn = _this
	        const val = obj._fn(...arg1, ...arg2)
	        delete obj._fn
	        return val
	    } 
	}

使用call实现bind

	Function.prototype.myBind = function(obj, ...arg1) {
	    obj = (typeof obj === 'object') ? obj : window
	    return (...arg2) => {
	        this.call(obj, ...arg1, ...arg2)
	    }
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值